TIL - #13 Security Deprecated

Quann·2022년 12월 26일
1

00. 개요

Spring Security 를 적용하다보면, Deprecated된 부분을 자주 만나볼 수 있다.
보안과 관련해 여러가지로 계속해서 업데이트가 진행되는 것 같은데, 이와 관련된 부분을 리팩터링하여 Deprecated를 없애보고자 한다.


01. 문제의 발견

@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 가 발생하는 것을 알 수 있는데, 이를 리팩터링 하고자 한다.


02. Deprecated

Deprecated는 더 이상 사용되지 않는 이라는 뜻으로, 해당 라이브러리 개발자가 앞으로 없어질 부분이나 취약점이 존재하는 부분에 대해 @Deprecated 애너테이션을 붙여 사용을 지양하기 위해 붙여지는 용어이다.

뜻에서 알 수 있다시피, 이런 부분을 발견하면 다른 코드로 바꿔서 해당 부분을 교체해주는 것이 좋다.

보통 사용하는 WebSecurityConfigurerAdapter가 Deprecated 된 상황인데, 이에 대한 이유로는 다음과 같다.

  • Component-Based Security Configuration 으로 사용자의 전환을 격려하기 위함
  • 동일한 개발 환경에서 오류를 방지하기 위함

따라서, 이와 관련된 클래스나 메서드들을 리팩터링 해야한다.


03. 문제의 해결

03.1. EnableGlobalMethodSecurity

해당 부분은 간단하게 해결할 수 있다.
해당 애너테이션을 들어가 내부문서를 확인해보면

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를 대신 사용해달라고 한다.
사용해주자~

03.2. WebSecurityConfigurerAdatper

해당 부분이 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을 설정하는 것을 대체할 수 있다.

03.3 authorizeRequests()

해당 부분의 내부 doc을 들어가면

Deprecated - Use authorizeHttpRequests() instead

을 확인할 수 있다.
authorizeRequests() 대신 authorizeHttpRequests() 를 사용해주자

또한, Spring Security 5.2.X부터 Lamda DSL이 추가되었다.
보안 필터에 대해 Lambda 형식으로 작성해 Indent를 적절하게 수정 가능하다


04. 완성된 코드

@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 된 줄도 없어 보기 매우 편안해졌다!


05. 오늘의 한 문단

코드는 계속 바뀐다.
계속 업데이트 할 줄 알아야한다.

참고 자료:
https://velog.io/@csh0034/Spring-Security-Config-Refactoring
https://docs.spring.io/spring-security
https://velog.io/@siunkimm/Spring-Security-Deprecated-WebSecurityConfigurerAdapter

profile
코드 중심보다는 느낀점과 생각, 흐름, 가치관을 중심으로 업로드합니다!

0개의 댓글