
WebSecurityConfigurerAdapter가 스프링시큐리티 5.7x 부터 지원중단 한다는 것을 보았습니다. 궁금증을 가지고, 구글링을 한 결과 실제 지원중단은 아니고 SecurityFilterChain Bean을 정의하는 것으로 권장하고 있다는 것을 확인하였습니다. 그 이유는 SecurityFilterChain Bean을 정의하는 것이 WebSecurityConfigurerAdapter를 상속받는 방식보다 더 명시적이고, 커스터마이징하기 쉬울 뿐만 아니라 필요한 보안 구성만을 선별해 적용할 수 있게 해주기 때문입니다.
그래서 저는 이 부분을 멋쟁이사자처럼12기 시큐리티 세션을 진행하면서 설명하기로 마음 먹었습니다.
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final JwtTokenProvider jwtTokenProvider;
@Autowired
public SecurityConfig(JwtTokenProvider jwtTokenProvider){
this.jwtTokenProvider = jwtTokenProvider;
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.httpBasic().disable() // REST API는 UI를 사용하지 않으므로 기본설정을 비활성화
.csrf().disable() // REST API는 csrf 보안이 필요 없으므로 비활성화
.sessionManagement()
.sessionCreationPolicy(
SessionCreationPolicy.STATELESS) // JWT Token 인증방식으로 세션은 필요 없으므로 비활성화
.and()
.authorizeRequests() // 리퀘스트에 대한 사용권한 체크
.antMatchers("/sign-api/sign-in", "/sign-api/sign-up",
"/sign-api/exception").permitAll() // 가입 및 로그인 주소는 허용
.antMatchers(HttpMethod.GET, "/board-api/**").permitAll() // product로 시작하는 Get 요청은 허용
.antMatchers("**exception**").permitAll()
.anyRequest().hasRole("ADMIN") // 나머지 요청은 인증된 ADMIN만 접근 가능
.and()
.exceptionHandling().accessDeniedHandler(new CustomAccessDeniedHandler())
.and()
.exceptionHandling().authenticationEntryPoint(new CustomAuthenticationEntryPoint())
.and()
.addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider),
UsernamePasswordAuthenticationFilter.class); // JWT Token 필터를 id/password 인증 필터 이전에 추가
}
@Bean
public PasswordEncoder passwordEncoder(){
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
@Override
public void configure(WebSecurity webSecurity) {
webSecurity.ignoring().antMatchers("/v2/api-docs", "/swagger-resources/**",
"/swagger-ui.html", "/webjars/**", "/swagger/**", "/sign-api/exception");
}
}
이 방법을 대신하여 SecurityFilterChain Bean을 직접 정의하는 코드로 변경해 보겠습니다. 방법은 간단합니다.
@Configuration
public class SecurityConfig {
private final JwtTokenProvider jwtTokenProvider;
@Autowired
public SecurityConfig(JwtTokenProvider jwtTokenProvider){
this.jwtTokenProvider = jwtTokenProvider;
}
@Bean
protected SecurityFilterChain configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.httpBasic().disable() // REST API는 UI를 사용하지 않으므로 기본설정을 비활성화
.csrf().disable() // REST API는 csrf 보안이 필요 없으므로 비활성화
.sessionManagement()
.sessionCreationPolicy(
SessionCreationPolicy.STATELESS) // JWT Token 인증방식으로 세션은 필요 없으므로 비활성화
.and()
.authorizeRequests() // 리퀘스트에 대한 사용권한 체크
.antMatchers("/sign-api/sign-in", "/sign-api/sign-up",
"/sign-api/exception").permitAll() // 가입 및 로그인 주소는 허용
.antMatchers(HttpMethod.GET, "/board-api/**").permitAll() // product로 시작하는 Get 요청은 허용
.antMatchers("**exception**").permitAll()
.anyRequest().hasRole("ADMIN") // 나머지 요청은 인증된 ADMIN만 접근 가능
.and()
.exceptionHandling().accessDeniedHandler(new CustomAccessDeniedHandler())
.and()
.exceptionHandling().authenticationEntryPoint(new CustomAuthenticationEntryPoint())
.and()
.addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider),
UsernamePasswordAuthenticationFilter.class); // JWT Token 필터를 id/password 인증 필터 이전에 추가
return httpSecurity.build();
}
@Bean
public PasswordEncoder passwordEncoder(){
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) -> web.ignoring().antMatchers("/v2/api-docs",
"/swagger-resources/**",
"/swagger-ui.html",
"/webjars/**",
"/swagger/**",
"/sign-api/exception");
}
}
클래스 정의 및 상속:
-WebSecurityConfigurerAdapter-
-SecurityFilterChain-
메소드 시그니처:
-WebSecurityConfigurerAdapter-
-SecurityFilterChain-
반환 타입:
-WebSecurityConfigurerAdapter-
-SecurityFilterChain-
두 코드 모두 HttpSecurity를 사용하여 Spring Security의 세부 설정을 구성합니다. 예를 들어, CSRF 보호 비활성화, 세션 관리 정책 설정, 접근 권한 체크, 예외 처리 등의 설정이 이에 해당합니다.
JWT 인증 필터 추가 방식도 동일합니다. 두 방식 모두 addFilterBefore 메소드를 사용하여 JwtAuthenticationFilter를 UsernamePasswordAuthenticationFilter 클래스 이전에 추가합니다.
.addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider),
UsernamePasswordAuthenticationFilter.class); // JWT Token 필터를 id/password 인증 필터 이전에 추가
WebSecurityCustomizer는 Spring Security의 FilterChainProxy에 대하여 커스터마이징을 위해 사용됩니다.
WebSecurityCustomizer를 구현하면 customize() 메서드를 오버라이딩하여 필요한 보안 구성을 추가하거나 필터를 무시할 수 있습니다.
스프링시큐리티에 대한 궁금증이 해결되었습니다. 트랜드에 맞춰서 권장하는 스타일대로 공부를 꾸준히 해야되겠다는 생각이 들었습니다.