Spring Security 를 적용하다보면, Deprecated된 부분을 자주 만나볼 수 있다.
보안과 관련해 여러가지로 계속해서 업데이트가 진행되는 것 같은데, 이와 관련된 부분을 리팩터링하여 Deprecated를 없애보고자 한다.
@RequiredArgsConstructor
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true) // Deprecated 발생
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { // Deprecated 발생
private final JwtUtil jwtUtil;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers("/resources/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests() // Deprecated 발생
.antMatchers("/user/**").hasRole("USER")
.formLogin()
.loginPage("/user/login").permitAll()
...
}
}
기존 Spring Security 적용을 위한 Configure 파일이다.
주석에 표시한 것과 같이 Deprecated 가 발생하는 것을 알 수 있는데, 이를 리팩터링 하고자 한다.
Deprecated는 더 이상 사용되지 않는
이라는 뜻으로, 해당 라이브러리 개발자가 앞으로 없어질 부분이나 취약점이 존재하는 부분에 대해 @Deprecated
애너테이션을 붙여 사용을 지양하기 위해 붙여지는 용어이다.
뜻에서 알 수 있다시피, 이런 부분을 발견하면 다른 코드로 바꿔서 해당 부분을 교체해주는 것이 좋다.
보통 사용하는 WebSecurityConfigurerAdapter
가 Deprecated 된 상황인데, 이에 대한 이유로는 다음과 같다.
따라서, 이와 관련된 클래스나 메서드들을 리팩터링 해야한다.
해당 부분은 간단하게 해결할 수 있다.
해당 애너테이션을 들어가 내부문서를 확인해보면
Enables Spring Security global method security similar to the
<global-method-security
> xml support.
More advanced configurations may wish to extend
...
Deprecated - Use EnableMethodSecurity instead
다음과 같이 적혀있다. - EnableMethodSecurity를 대신 사용해달라고 한다.
사용해주자~
해당 부분이 Deprecated 되어, WebSecurityConfigurerAdapter를 상속받지 않고 필터체인을 구성해야한다.
이를 위해, SecurityFilterChain을 Bean으로 등록하는 메서드를 선언하여 해결이 가능하다.
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
// h2-console 사용 및 resources 접근 허용 설정
return (web) -> web.ignoring()
.requestMatchers(PathRequest.toH2Console())
.requestMatchers(PathRequest.toStaticResources().atCommonLocations());
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeHttpRequests()
.requestMatchers("/api/user/**").permitAll()
...
http.formLogin().loginPage("/api/user/login-page").permitAll();
http.exceptionHandling().accessDeniedPage("/api/user/forbidden");
return http.build();
}
다음과 같이, HttpSecurity를 주입받아, http에 대한 설정들을 진행 해준 뒤, 마지막에 .build() 를 통한 SecurityFilterChain 을 직접 등록해 사용하는 방식이다.
또한, WebSecurityCustomizer의 Bean 등록을 통해 기존 WebSecurity를 주입받아 ignoring을 설정하는 것을 대체할 수 있다.
해당 부분의 내부 doc을 들어가면
Deprecated - Use authorizeHttpRequests() instead
을 확인할 수 있다.
authorizeRequests()
대신 authorizeHttpRequests()
를 사용해주자
또한, Spring Security 5.2.X부터 Lamda DSL이 추가되었다.
보안 필터에 대해 Lambda 형식으로 작성해 Indent를 적절하게 수정 가능하다
@Configuration
@RequiredArgsConstructor
@EnableWebSecurity // 스프링 Security 지원을 가능하게 함
@EnableMethodSecurity(securedEnabled = true) // @Secured 어노테이션 활성화
public class WebSecurityConfig {
private final JwtUtil jwtUtil;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
// h2-console 사용 및 resources 접근 허용 설정
return (web) -> web.ignoring()
.requestMatchers(PathRequest.toH2Console())
.requestMatchers(PathRequest.toStaticResources().atCommonLocations());
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(authorize -> authorize
.requestMatchers("/api/user/**").permitAll()
.requestMatchers("/api/search").permitAll()
.requestMatchers("/api/shop").permitAll()
.anyRequest().authenticated()
.and().addFilterBefore(new JwtAuthFilter(jwtUtil), UsernamePasswordAuthenticationFilter.class))
.formLogin(form -> form
.loginPage("/api/user/login-page").permitAll())
.exceptionHandling(exception -> exception
.accessDeniedPage("/api/user/forbidden"))
.build();
}
}
위 내용을 바탕으로 다음과 같이 업데이트 되었다.
Indent도 변화하고, Deprecated 된 줄도 없어 보기 매우 편안해졌다!
코드는 계속 바뀐다.
계속 업데이트 할 줄 알아야한다.
참고 자료:
https://velog.io/@csh0034/Spring-Security-Config-Refactoring
https://docs.spring.io/spring-security
https://velog.io/@siunkimm/Spring-Security-Deprecated-WebSecurityConfigurerAdapter