일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 파라미터 그룹
- springboot
- AWS
- 피리티어
- 자바스터디
- java
- RDS
- 예외
- Spring
- https
- 이펙티브자바
- 보안 그룹
- exception
- JVM
- 이펙티브 자바
- 자바
- spring-security
- Checked Exception
- ec2
- Annotation
- 생각정리
- Unchecked Exception
- Final
- 바이트코드
- error
- bytecode
- try-with-reources
- Effective Java
- Today
- Total
개발 일지
[Spring Security] WebSecurityConfigurerAdapter is deprecated
junjun_ 2022. 12. 18. 17:46jwt를 이용한 로그인을 구현하기 위해 예전에 사용했던 Security설정을 복붙 했더니 'org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter' is deprecated 이란 문구가 뜨면서 WebSecurityConfigurerAdapter을 extends 할 수 없는 이슈가 있었습니다.
Deprecated
Use a org.springframework.security.web.SecurityFilterChain Bean to configure HttpSecurity or a WebSecurityCustomizer Bean to configure WebSecurity
더 이상 사용되지 않음
org.springframework.security.web.SecurityFilterChain Bean을 사용하여 HttpSecurity를 구성하거나 WebSecurityCustomizer Bean을 사용하여 WebSecurity를 구성하십시오.
해당 이슈에 대한 내용은 공식문서 에 정리되어 있습니다.
결론부터 얘기하면
- Spring Security 5.7.0-M2 부터는 구성 요소 기반 보안 설정을 사용하도록 권장
- 더 이상 WebSecurityConfigurerAdapter을 사용되지 않는다고 합니다.
before(이제 사용되지 않음)
- HttpSecurity 구성할때 WebSecurityConfigurerAdapter 상속 후, configure 메서드를 오버라이딩 하여 설정하는 방식
After
- SecurityFilterChain를 빈으로 등록하는 방식을 권장
SecurityFilterChain 을 빈으로 등록
공식문서에는 다음과 같이 설명되어 있습니다.
In Spring Security 5.7.0-M2 we deprecated the WebSecurityConfigurerAdapter, as we encourage users to move towards a component-based security configuration.
To assist with the transition to this new style of configuration, we have compiled a list of common use-cases and the suggested alternatives going forward.
In the examples below we follow best practice by using the Spring Security lambda DSL and the method
HttpSecurity#authorizeHttpRequests to define our authorization rules
Configuring HttpSecurity
In Spring Security 5.4 we introduced the ability to configure HttpSecurity by creating a SecurityFilterChain bean.
간단하게 정리하자면HttpSecurity 구성할때 WebSecurityConfigurerAdapter 상속 후, configure 메서드를 오버라이딩 하여 설정하는 방식을 사용하지 않고 앞으로는 SecurityFilterChain를 빈으로 등록하는 방식을 권장한다는 것입니다.
아래는 WebSecurityConfigurerAdapterHTTP Basic으로 모든 엔드포인트를 보호하는 를 사용하는 구성의 예입니다.
before
- WebSecurityConfigurerAdapter 상속 후, configure 메서드를 오버라이딩 방식
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authz) -> authz
.anyRequest().authenticated()
)
.httpBasic(withDefaults());
}
}
앞으로 이 작업을 수행하는 권장 방법은 SecurityFilterChainbean을 등록하는 것입니다.
after
- SecurityFilterChain을 bean으로 등록하는 방식
@Configuration
public class SecurityConfiguration {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authz) -> authz
.anyRequest().authenticated()
)
.httpBasic(withDefaults());
return http.build();
}
}
코드 자체는 많이 달라지지 않았습니다. 차이점은
- @Bean 어노테이션을 이용하여 빈으로 등록한 것과
- return 반환 값이 있다는 것입니다.
결과적으로 원래였으면 상속받아서 오버라이드를 통해 사용했어야 했던 것들을 @Bean 애너테이션을 통해 스프링 빈으로 등록해 주면서 spring에서 자동으로 적용시켜주는 것을 알 수 있습니다.
.addFilter
SecurityFilterChain에 필터(JwtAuthenticationFilter)를 등록할 때 WebSecurityConfigurerAdapter가 빈으로 갖고 있는 authenticationManager 빈을 생성자를 통해 JwtAuthenticationFilter에 주입시켰으나 WebSecurityConfigurerAdapter가 deprecated되면서authenticationManager 빈을 작성해 줘야합니다.
bfore
- authenticationManager () 으로 바로 주입가능
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager(), userRepository))
After
- authenticationManager 빈 작성 후
- 작성한 빈을 통해 주입시켜줘야 한다
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.httpBasic().disable() /*JWT 이외의 session, http basic, loginform 등의 인증방식을 제거 */
.formLogin().disable()
.sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeRequests(authorizeRequests ->
authorizeRequests
.antMatchers("/api/v1/sign-up").permitAll()
.antMatchers("/api/v1/login").permitAll()
.anyRequest().authenticated()
)
.addFilter(new JwtAuthenticationFilter(authenticationManager(http.getSharedObject(AuthenticationConfiguration.class)), jwtUtil, mapper))
.addFilter(new JwtAuthorizationFilter(authenticationManager(http.getSharedObject(AuthenticationConfiguration.class)), userDetailsService, jwtUtil));
return http.build();
}
Spring Security Config 최신화 적용하기
예전 SecurityConfig.java 코드
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
private final CorsConfig corsConfig;
private final UserRepository userRepository;
private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
@Override
public void configure(WebSecurity web) {
web.ignoring()
.antMatchers(
"/h2-console/**"
,"/favicon.ico"
,"/error"
);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilter(corsConfig.corsFilter())
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.formLogin().disable()
.httpBasic().disable()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager(), userRepository))
.authorizeRequests()
.antMatchers("/api/v1/user/**")
.access("hasRole('ROLE_USER') or hasRole('ROLE_MANAGER') or hasRole('ROLE_ADMIN')")
.antMatchers("/api/v1/manager/**")
.access("hasRole('ROLE_MANAGER') or hasRole('ROLE_ADMIN')")
.antMatchers("/api/v1/admin/**")
.access("hasRole('ROLE_ADMIN')")
.anyRequest().permitAll();
}
바꾼 코드
public class SecurityConfig {
private final AuthenticationFailureHandler authenticationFailureHandler;
private final AuthenticationSuccessHandler authenticationSuccessHandler;
private final ObjectMapper mapper;
private final CustomUserDetailService userDetailsService;
private final JwtUtil jwtUtil;
@Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
AuthenticationManager authenticationManager = authenticationManager(http.getSharedObject(AuthenticationConfiguration.class));
JwtAuthenticationFilter jwtAuthenticationFilter
= new JwtAuthenticationFilter(authenticationManager, mapper);
jwtAuthenticationFilter.setAuthenticationFailureHandler(authenticationFailureHandler);
jwtAuthenticationFilter.setAuthenticationSuccessHandler(authenticationSuccessHandler);
http
.csrf().disable()
.httpBasic().disable() /*JWT 이외의 session, http basic, loginform 등의 인증방식을 제거 */
.formLogin().disable()
.sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeRequests(authorizeRequests ->
authorizeRequests
.antMatchers("/api/v1/sign-up").permitAll()
.antMatchers("/api/v1/login").permitAll()
.anyRequest().authenticated()
)
.addFilter(jwtAuthenticationFilter)
.addFilter(new JwtAuthorizationFilter(authenticationManager, userDetailsService, jwtUtil));
return http.build();
}
정리
제가 필요한 설정 위주로 정리하였기 때문에 더 자세한 내용은 공식문서를 확인하면 좋을 것 같습니다.
기술은 계속해서 추가되고, 바뀌기 때문에 공부는 계속되어야겠습니다.. ㅎㅎ