[Spring Security] Security 인증, 인가 설정
- [ Backend ]/Spring
- 2023. 10. 16.
개요
작년에 스프링 시큐리티를 처음 공부했을 때(https://eckrin.tistory.com/103) 시큐리티 구조와 초기 설계에 대해서 글을 썼던 적이 있는데, 실제로 사용하면서 궁금했던 점들을 정리해보고자 한다.
SecurityFilterChain과 WebSecurityCustomizer
먼저 시큐리티 설정을 위해서 Configuration 파일을 만들 때 httpbasic, csrf, cors 등 다양한 설정을 했는데, 그 중 antMatchers(스프링 3.x버전에서는 requestMatchers로 대체)를 사용하는 SecurityFilterChain과 WebSecurityCustomizer에 대한 설명을 해보고자 한다.
SecurityFilterChain에서는 특정 경로로 들어오는 요청 패턴에 대한 인증, 인가에 대한 제어를 할 수 있다. 아래 두 가지 예시를 보자.
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests(authorizeRequests ->
authorizeRequests
.antMatchers("/auth/**").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.httpBasic(withDefaults()); // Optional, for HTTP Basic Authentication
return http.build();
}
...
}
- /auth/** 패턴의 요청은 .antMatchers("/auth/**").permitAll() 설정에 의해 "인증"을 필요로 하지 않으며 모든 사용자에게 허용된다.
- /admin/** 패턴의 요청은 .antMatchers("/admin/**").hasRole("ADMIN") 설정에 의해 "인증"과 "ROLE_ADMIN" 권한을 필요로 한다.
- 그 외의 모든 요청은 .anyRequest().authenticated() 설정에 의해 "인증"과 "인가"를 필요로 한다.
- 모든 요청은 시큐리티 필터를 통과한다.
즉 SecurityFilterChain에서 authorizeHttpRequest() 설정을 통해서 인증을 제외한다고 해서 필터를 통과하지 않는 것은 아니다. 스프링 시큐리티를 Jwt와 함께 사용하게 되는 경우가 있는데, 시큐리티 필터 체인에 Jwt 헤더 검증 로직을 넣게 되면 이렇게 설정할 경우 인증을 원하지 않는 요청에서도 exception이 던져지는 것을 볼 수 있다. 무슨 말이나면,
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
private final JwtTokenProvider tokenProvider;
private final ExceptionHandleFilter exceptionFilter;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
....
.authorizeHttpRequests(authorize ->
authorize
.requestMatchers(
"/auth/**"
).permitAll() //로그인, 회원가입,
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() //cors
.anyRequest().authenticated()
)
.addFilterBefore(new JwtAuthenticationFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(exceptionFilter, JwtAuthenticationFilter.class);
return http.build();
...
}
위와 같이 설정한 후, /auth/** 요청의 인가처리를 배제했으므로 문제가 생기지 않을 것이라고 예상했었는데, 커스텀하여 추가한 JwtAuthenticationFilter를 통과하다 던져진 exception으로 인해서 문제가 발생하였다.
필터를 아예 통과하지 않게 하기 위해서는 WebSecurityCustomizer를 사용하면 된다.
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return web -> web.ignoring().requestMatchers(
"/auth/**"
);
}
'[ Backend ] > Spring' 카테고리의 다른 글
[Spring] 동시성 이슈를 고려한 스프링 프로젝트 설계 (0) | 2024.01.03 |
---|---|
[Spring] 비동기 환경에서 트랜잭션은 어떻게 동작할까? (0) | 2023.12.08 |
[Spring] 스프링과 Tomcat (0) | 2023.02.16 |
[Spring Security] @AuthenticationPrincipal, HandlerMethodArgumentResolver (0) | 2022.11.13 |
[Spring Security] jwt를 활용하여 시큐리티 커스텀하기 (0) | 2022.08.13 |