본문 바로가기
공부 기록

[SPRING SECURITY] WebSecurityConfigurerAdapter Deprecated - 최신 설정 방법

by 타태 2022. 11. 12.

 

2022.10.09 - [공부 기록] - 스프링 시큐리티의 우아한 멀티 타입 빌더

 

[SPRING SECURITY]우아한 멀티 타입 빌더

스프링 시큐리티를 사용한다면 우리는 WebSecurityConfigurerAdapter 를 확장하는 클래스를 구현해야하고 아래와 같은 설정을 하게 된다. 처음 마주하면 이게 무슨 복잡한 빌더인가? 이 설정을 다 알아

ktae23.tistory.com

 

 

스프링 시큐리티를 사용하려면 우리는 WebSecurityConfigurerAdapter 상속받아 확장하는 설정 클래스를 작성하게 된다.

하지만 Spring Security 5.2릴리스부터는 이를 상속받지 않고 람다를 사용하여 HTTP 보안을 구성할 수 있는 DSL에 대한 개선 사항이 포함되었다.

 

Spring Security Lambda DSL에 대해서는 이 문서를 참고하자. 

 

따라서 이번 포스팅에서는 DeprecatedWebSecurityConfigurerAdapter 를 사용하지 않고 Http 보안 설정을 하는 방법을 소개한다.

 

백문이 불여일견 코드부터 보자

 

기존 방식 - void configure(HttpSecurity http) 오버라이딩

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .headers().cacheControl().disable()
            .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .httpBasic().disable()
            .formLogin().disable()
            .cors().configurationSource(corsConfigurationSource())
            .and()
            .csrf().disable()
            .authorizeRequests()
            .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
            .mvcMatchers("/").permitAll()
            .anyRequest().authenticated()
            .and()
            .logout()
            .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
            .logoutSuccessUrl("/").and()
            .exceptionHandling()
            .authenticationEntryPoint(
            	(request, response, authException) -> response.sendRedirect("/login")
            )
        ;
    }

변경된 방식 - SecurityFileterChain fileterChain(HttpsSecurity http) Bean

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
            .headers(headers -> headers.cacheControl().disable())
            .sessionManagement(sessionManagement -> 
            	sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            )
            .httpBasic(AbstractHttpConfigurer::disable)
            .formLogin(AbstractHttpConfigurer::disable)
            .cors(cors -> cors.configurationSource(corsConfigurationSource()))
            .csrf(AbstractHttpConfigurer::disable)
            .authorizeRequests(request ->
                request.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
                    .mvcMatchers("/").permitAll()
                    .anyRequest().authenticated()
            )
            .logout(logout ->
                logout
                	.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                    .logoutSuccessUrl("/")
            )
            .exceptionHandling(exception ->
                exception.authenticationEntryPoint(
                	(request, response, authException) -> response.sendRedirect("/login")
                )
            )
            .build();
    }

 


 

기존 방식 - void configure(WebSecurity web) 오버라이딩

    @Override
    public void configure(WebSecurity web) {
        web
            .ignoring()
            .requestMatchers(
                PathRequest.toStaticResources().atCommonLocations()
            )
            .antMatchers("/error")
        ;
    }

변경된 방식 - WebSecurityCustomizer configure() Bean

    @Bean
    public WebSecurityCustomizer configure() {
        return web -> web.ignoring()
            .requestMatchers(
                PathRequest.toStaticResources().atCommonLocations()
            )
            .antMatchers("/error")
            ;
    }

 

** 추가 ignore를 사용하면 친절히 로그에서 ingnore 대신 authorizeHttpRequests을 통해 permitAll을 사용하기를 권장한다.

You are asking Spring Security to ignore org.springframework.boot.autoconfigure.security.servlet.StaticResourceRequest$StaticResourceRequestMatcher@3ece79fe. This is not recommended -- please use permitAll via HttpSecurity#authorizeHttpRequests instead.

아래 설정을 HttpSecurity 체인에 추가해주자.

.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()​

 


기존 방식 - void configure(AuthenticationManagerBuilder auth) 오버라이딩

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .userDetailsService(userDetailsService())
            .passwordEncoder(bCryptPasswordEncoder());
    }

 

변경된 방식 - AuthenticationManager authenticationManager(AuthenticationManagerBuilder auth) Bean

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationManagerBuilder auth) throws Exception {
        return auth.userDetailsService(userDetailsService)
            .passwordEncoder(bCryptPasswordEncoder()).and().build();
    }

 


 

이처럼 기존 WebSecurityConfigurerAdapter를 상속받아확장하는 방식 대신 람다를 사용하고 으로 등록함으로써 얻게 되는 이점으로 아래의 세 가지를 소개하고 있다.

스프링 진영에서의 함수형 프로그래밍의 장점은 이미 많은 곳에 자리 잡고 있는 것 같다.

Goals of the Lambda DSL
The Lambda DSL was created to accomplish to following goals:

Automatic indentation makes the configuration more readable.
- 자동 들여 쓰기는 구성을 더 읽기 쉽게 만듭니다.

The is no need to chain configuration options using .and()
- .and() 메서드를 통해 구성 옵션을 연결할 필요가 없습니다

The Spring Security DSL has a similar configuration style to other Spring DSLs such as Spring Integration and Spring Cloud Gateway.
- Spring Security DSL은 Spring Integration 및 Spring Cloud Gateway와 같은 여타 Spring DSL과 유사한 구성 스타일을 가지고 있습니다.

- 스프링 시큐리티의 and 메서드에 대해 궁금하다면 참고

더 자세히 알고 싶다면 아래 문서를 확인하면 정말 자세하고 친절하게 나와 있으니 확인해보시길 바란다.

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/8804

 

Configure HTTP Security without extending WebSecurityConfigurerAdapter · Issue #8804 · spring-projects/spring-security

Expected Behavior Similar to the WebFlux security configuration, we should add the capability to configure HTTP Security by registering a SecurityFilterChain bean, in Servlet applications. @Bean Se...

github.com

https://docs.spring.io/spring-security/reference/servlet/authorization/authorize-http-requests.html

 

Authorize HttpServletRequests with AuthorizationFilter :: Spring Security

By default, the AuthorizationFilter does not apply to DispatcherType.ERROR and DispatcherType.ASYNC. We can configure Spring Security to apply the authorization rules to all dispatcher types by using the shouldFilterAllDispatcherTypes method:

docs.spring.io

 

 

P.S

번외로 기존의 어댑터 상속 방식을 사용할 때도 람다로 구성하면 .and()없이 구성이 가능하다.

기존 방식 (람다) - void configure(HttpSecurity http) 오버라이딩

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .headers(headers -> headers.cacheControl().disable())
            .sessionManagement(sessionManagement -> sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .httpBasic(AbstractHttpConfigurer::disable)
            .formLogin(AbstractHttpConfigurer::disable)
            .cors(cors -> cors.configurationSource(corsConfigurationSource()))
            .csrf(AbstractHttpConfigurer::disable)
            .authorizeRequests(request ->
                request.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
                    .mvcMatchers("/", "/accounts/join", "/accounts/login", "/images/**").permitAll()
                    .anyRequest().authenticated()
            )
            .logout(logout ->
                logout.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                    .logoutSuccessUrl("/")
            )
            .exceptionHandling(exception ->
                exception.authenticationEntryPoint((request, response, authException) ->
                    response.sendRedirect("/login")
                )
            )
        ;
    }

 

반응형

댓글