웹/Spring

Spring Security를 이용한 세션 확인과 커스텀 인가

Themion 2022. 4. 25. 15:36

백엔드에서 세션을 다루다 보면 세션 정보를 확인해야 할 일이 있다. 사용자의 비밀번호를 바꾼다거나, 사용자가 작성한 게시물을 확인할 때에는 해당 요청을 보낸 사용자 정보를 반드시 확인해야 하는데, Spring Security에서는 간단하게 세션의 확인과 인가가 가능하다.

우선 세션의 확인은 Controller 단에서 이루어지는데, Spring의 Controller에 @AuthenticationPrincipal 어노테이션을 가진 파라미터를 설정하면 요청을 보낸 세션의 username을 가져올 수 있다.

// ... 기존 코드들 ...

@RestController
public class UserController {

    // ... 기존 코드들 ...

    @RequestMapping(value = "/path", method = RequestMethod.POST)
    public void thisRequestNeedsUsername(
        @AuthenticationPrincipal String username
    ) {
        // JWT 세션에서 Subject로 등록한 값이 username에 할당된다
    }

    // ... 기존 코드들 ...
    
}

인가 역시 간단하다. Spring Security는 각 경로와 메소드에 대한 접근 권한을 인가를 통해 관리하는데, hasAuthority나 hasRole과 같은 Spring Security에 내장된 인가 메소드가 아니라 직접 구현한 인가 메소드를 활용할 수도 있다.

@Configuration
@EnableWebSecurity
@AllArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final UserService userService;
    private final PasswordEncoder encoder;
    private final UserDetailsService userDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers(HttpMethod.POST, "/test1")
                    .access("@securityUtils.CustomAuthorization(authentication)")
                .antMatchers(HttpMethod.POST, "/test2/{path}")
                    .access("@securityUtils.CustomAuthorization(authentication,#path)")
                
    }

}
@Component
@AllArgsConstructor
public class SecurityUtils {

    // ... 기존 코드들 ...

    public boolean CustomAuthorization(Authentication auth) {
    
        // Spring Security에서 관리하는 세션의 사용자 이름을 가져온다
        String username = auth.getName();
        
        // ... 인가 코드들 ...
    }

    public boolean CustomAuthorization(Authentication auth, Object path) {
    
        // Spring Security에서 관리하는 세션의 사용자 이름을 가져온다
        String username = auth.getName();
        // path는 Object 타입뿐 아니라 String 혹은 Long 등 여러 타입으로 가져올 수 있다
        String str = (String) path;
        
        // ... 인가 코드들 ...
    }
   
    // ... 기존 코드들 ...

}

위와 같이 antMatchers에서 SpEL(스프링 표현 언어)로 나타낸 인가 함수를 파라미터로 지닌 메소드 access를 호출하는데, 이 SpEL로 표현한 함수의 기본 인자로 Authentication 타입이 존재하므로 getPrincipal 혹은 getName을 이용해 요청을 보낸 세션의 사용자 이름을 사용할 수 있다. 또한, 특정 path를 인자로 사용한다면 해당 path 역시 path에 맞는 타입으로 파라미터화 하여 인가 함수에서 사용할 수 있다.