네로개발일기

개발자 네로의 개발 일기, 자바를 좋아합니다 !

반응형

1. Spring Security Config 리팩토링

Spring Security 버전업이 되면서 기존 프로젝트의 문제점이 생기기 시작했다. 해당 문제점에 대해 알아보고 리팩토링을 하자.

 

  • WebSecurityConfigurerAdapter 상속 제거
  • Resource Filter Chain 설정

2. 개발 환경

  • Spring Boot 2.7.6
  • Spring Security 5.7.6
  • Java 11
  • Gradle 7.5.1

3. 기존 SecurityConfig

일반적으로 많이 사용하는 SecurityConfig이다.

@Configuration
@EnableWebSecurity // Spring Security 활성화
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    public void configure(WebSecurity web) {
        // resource 에 대해 Spring Security FilterChain 제외
        web.ignoring().antMatchers("/resources/**");
    }
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .mvcMatchers("/", "/login", "/sign-up", "/check-email-token"
                        , "/email-login", "/check-email-login", "/login-link", "/login-by-email").permitAll()
                .mvcMatchers(HttpMethod.GET, "/profile/*").permitAll()
                .anyRequest().authenticated().and()
            .formLogin()
                .loginPage("/login").permitAll()
            .logout()
                .logoutSuccessUrl("/");
    }
}

ant pattern을 이용한 ignore 처리가 권장되지 않는다.

해당 설정으로 실행시 하단과 같은 WARN 로그가 발생한다.

You are asking Spring Security to ignore Ant [pattern='/resource/**']. This is not recommended -- please use permitAll via HttpSecurity#authorizeHttpRequests instead.

이 로그는 Spring Security 5.5.x에 추가되었으며 Spring Security Github Issue에서 확인할 수 있다. 간략히 요약해보자면,

web.ignoring()은 Spring Security 가 해당 엔드포인트에 보안헤더 또는 기타 보호 조치를 제공할 수 없다. 대신에 permitAll() 메서드를 사용하여 권한 검증 없이 요청을 보호할 수 있다. 이러한 이유때문에 해당 경고메시지를 알려주었다.

또한, static resource에 대해 SecurityFilterChain을 추가하는 방법에 대해서 알려주었는데 해당 방안은 밑에서 알아보겠습니다.

 

Spring Security 5.7.x 부터 WebSecurityConfigurerAdapter Deprecate 문제

Spring Security 5.7.x 부터 WebSecurityConfigurerAdapter가 Deprecated 되었다.

https://spring.io/blog/2022/02/21/spring-security-without-the-websecurityconfigureradapter

 

4. SecurityConfig 리팩토링

WebSecurityConfigurerAdapter를 상속하기않고 적용

WebSecurityConfigurerAdapter를 상속하지 않고 필터체인을 구성하는 방법으론 SecurityFilterChain을 Bean으로 선언하는 방법이 있다. 이때 HttpSecurity를 주입받아 사용하면 된다.

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean   
    public WebSecurityCustomizer webSecurityCustomizer() {
        return web -> web.ignoring().antMatchers("/resources/**");   
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .mvcMatchers("/", "/login", "/sign-up", "/check-email-token"
                        , "/email-login", "/check-email-login", "/login-link", "/login-by-email").permitAll()
                .mvcMatchers(HttpMethod.GET, "/profile/*").permitAll()
                .anyRequest().authenticated();

        http.formLogin()
                .loginPage("/login")
                .permitAll();

        http.logout()
                .logoutSuccessUrl("/");

        return http.build();
    }
}

WebSecurityConfigurerAdapter 상속을 제거하고 WebSecurityCustomizer 선언과 HttpSecurity의 build() 호출 후, 리턴하여 Bean으로 등록한다.

HttpSecurityConfiguration을 확인해보면 HttpSecurity에 기본적인 설정을 한 후, prototype으로 Bean을 등록한다. 따라서 매번 주입받을 때 마다 새로운 인스턴스를 주입받을 수 있다.

 

➤ 주의사항

WebSecurityConfigurerAdapter 상속과 SecurityFilterChain Bean 등록을 동시에 사용할 경우 아래와 같은 로그가 발생한다.

Caused by: java.lang.IllegalStateException: Found WebSecurityConfigurerAdapter as well as SecurityFilterChain. Please select just one.

 

Resource 용 SecurityFilterChain 적용

WebSecurityCustomizer 설정을 제거하고 @Order(0) 을 추가하여 먼저 FilterChain 을 타도록 지정한다. resources(css, js 등) 의 경우 securityContext 등에 대한 조회가 불필요 하므로 disable 합니다.

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .mvcMatchers("/", "/login", "/sign-up", "/check-email-token"
                        , "/email-login", "/check-email-login", "/login-link", "/login-by-email").permitAll()
                .mvcMatchers(HttpMethod.GET, "/profile/*").permitAll()
                .anyRequest().authenticated();

        http.formLogin()
                .loginPage("/login")
                .permitAll();

        http.logout()
                .logoutSuccessUrl("/");

        return http.build();
    }

    @Bean
    @Order(0)
    public SecurityFilterChain resources(HttpSecurity http) throws Exception {
        return http.requestMatchers(matchers -> matchers.antMatchers( "/resources/**"))
                .authorizeHttpRequests(authorize -> authorize.anyRequest().permitAll())
                .requestCache(RequestCacheConfigurer::disable)
                .securityContext(AbstractHttpConfigurer::disable)
                .sessionManagement(AbstractHttpConfigurer::disable).build();
    }
}

 

 

 

 출처 

https://spring.io/blog/2022/02/21/spring-security-without-the-websecurityconfigureradapter

 

Spring Security without the WebSecurityConfigurerAdapter

<p>In Spring Security 5.7.0-M2 we <a href="https://github.com/spring-projects/spring-security/issues/10822">deprecated</a> the <code>WebSecurityConfigurerAdapter</code>, as we encourage users to move towards a component-based security configuration.</p> <p

spring.io

https://github.com/spring-projects/spring-security/issues/10938

 

WARN when ignoring antMatchers - please use permitAll · Issue #10938 · spring-projects/spring-security

When I use web.ignoring().antMatchers() I'd like to see a DEBUG message instead of a WARNING for each ignored pattern. I'm confused by the message saying it's not recommended and I shou...

github.com

https://velog.io/@csh0034/Spring-Security-Config-Refactoring

 

[Spring Security] Config Refactoring

WebSecurityConfigurerAdapter Deprecated, Lambda DSL 적용, Resource Filter Chain 설정

velog.io

 

728x90
반응형
blog image

Written by ner.o

개발자 네로의 개발 일기, 자바를 좋아합니다 !