티스토리 뷰

자바와 스프링에 대한 기본 지식을 기르기 위해 토이 프로젝트를 시작했습니다.

 

토이 프로젝트로 배우는 자바 스프링 [0]. prologue

자바와 스프링에 대한 기본 지식을 기르기 위해 토이 프로젝트를 시작했습니다. 프론트 코드 : https://github.com/laboratory-kkoon9/connector_front GitHub - laboratory-kkoon9/connector_front Contribute to laboratory-kkoon9/co

kkoon9.tistory.com

프론트 코드 : https://github.com/laboratory-kkoon9/connector_front

 

GitHub - laboratory-kkoon9/connector_front

Contribute to laboratory-kkoon9/connector_front development by creating an account on GitHub.

github.com

백엔드 코드 : https://github.com/laboratory-kkoon9/connector_back

 

GitHub - laboratory-kkoon9/connector_back

Contribute to laboratory-kkoon9/connector_back development by creating an account on GitHub.

github.com

배경

다음 코드는 WebSecurityConfigurerAdapter를 사용해 WebSecurity에 대한 config를 설정해주는 클래스입니다.

package com.connector.global.config;

import com.connector.global.filter.ExceptionHandlerFilter;
import com.connector.global.filter.JwtTokenFilter;
import lombok.RequiredArgsConstructor;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.web.cors.CorsUtils;

@EnableWebSecurity
@RequiredArgsConstructor
@Order(300)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private final JwtTokenFilter jwtTokenFilter;
    private final ExceptionHandlerFilter exceptionHandlerFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable().cors()
                .and()
                .authorizeRequests()
                .antMatchers(HttpMethod.GET, "/api/**").permitAll()
                .antMatchers(HttpMethod.POST, "/api/**").permitAll()
                .antMatchers(HttpMethod.PUT, "/api/**").permitAll()
                .antMatchers(HttpMethod.DELETE, "/api/**").permitAll()
                .antMatchers(
                        "/swagger-ui/**",
                        "/v3/api-docs/**",
                        "/swagger-ui.html")
                .permitAll()
                .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .antMatcher("/**")
                .addFilterBefore(jwtTokenFilter, BasicAuthenticationFilter.class)
                .addFilterBefore(exceptionHandlerFilter, JwtTokenFilter.class);
    }
}

스프링에서는 WebSecurityConfigurer 인스턴스를 만들기 위한 편리한 기본 클래스인 WebSecurityConfigurerAdapter를 제공합니다.

WebSecurityConfigurer가 무엇인지는 아래에서 살펴봅시다. 

WebSecurityConfigurerAdapter 클래스가 deprecated 되었는데, 그 이유와 어떤 걸 사용해야 하는지 이번 포스팅에서 다뤄보려 합니다.

WebSecurityConfigurer

WebSecurityConfigurer는 커스터마이징된 WebSecurity를 허용해주는 역할을 합니다.

대부분의 경우 사용자는 EnableWebSecurity를 사용하고 SecurityFilterChain 빈을 만드는 Configuration을 생성합니다.

이는 EnableWebSecurity 어노테이션에 의해 자동으로 WebSecurity에 적용됩니다.

WebSecurity

WebSecurity는 spring Security FilterChain으로 알려진 FilterChainProxy를 생성하는 WebSecurityConfiguration을 만드는 역할을 합니다.

spring Security FilterChain은 DelegatingFilterProxy가 위임하는 Filter입니다.

WebSecurity에 대한 커스터마이징은 WebSecurityConfigurer를 생성하거나 WebSecurityCustomizer 빈을 노출하여 수행할 수 있습니다.

WebSecurityConfigurerAdapter는 deprecated 됐을까?

가볍게 WebSecurityConfigurerAdapter의 역할이 무엇인지 알아봤습니다.

허나 왜 deprecated 되었을까요?

spring-security github에 들어가보니 WebSecurityConfigurerAdapter 설계의 결함이 많아 수정하기 어려운 문제가 많다고 합니다.

1. Does Not Expose Beans

첫 번째 이유는 Bean을 노출시키는 것이 아니라 auto Configuration을 위해 기본 애플리케이션이나 스프링 부트에서 사용할 수 없는 개체를 자동으로 생성한다는 점입니다.

이로 인해 스프링 부트에서는 AuthenticationManager를 생성해야 하는지에 대한 여부를 알 수 없다고 합니다.

또한 사용자가 자신의 코드에서 AuthenticationManager를 빈으로 활용하는 것을 어렵게 만든다고 하네요.

2. Beans Cannot be Injected via Method Arguments

두 번째 문제는 메서드 시그니처의 정적 특성 때문에 Security Configuration이 메서드 인수를 통해 JavaBean으로 전달되는 모범 사례를 따르지 않는다는 점입니다.

대신 종속성을 멤버 변수에 주입하거나 메서드 레퍼런스를 통해 해결해야 합니다.

본질적으로 잘못된 것은 없지만 몇 가지 제한 사항을 유발하는 모범 사례를 따르지 않는다고 하네요.

Bean 종속성에 메서드 인수를 사용할 경우 개체 생성이 이루어지기 전에 Spring은 Bean이 어떤 개체인지 정확히 알고 있습니다.

이는 최소 개체 그래프를 만들 수 있음을 의미합니다.

이에 대한 단점은 chat GPT에서 찾아봤습니다.

멤버 변수(구성 클래스의 @Autowired 메서드)를 사용할 경우, Spring은 Bean을 해결하기 위해 전체 @Configuration을 초기화해야 합니다.
메서드 레퍼런스를 사용에서도 유사한 문제가 발생합니다.

Bean을 해결하기 위해 method reference를 사용할 때도 비슷한 문제가 발생합니다.

이 두 가지 결함에 대해서는 직접적으로 와닿지는 않습니다.

직접적으로 와닿을 수 있는 예시는 알게 되면 다른 포스팅으로 다뤄보겠습니다!

without WebSecurityConfigurerAdapter

이젠 WebSecurityConfigurerAdapter 없이 설정하는 방법에 대해 알아봅시다.

해당 링크에서는 따르길 SecurityFilterChain bean을 등록하여 HTTP Security를 구성하는 기능을 추가하라고 합니다.

 

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

아래 코드는 SecurityFilterChain을 Bean으로 등록하는 코드입니다.

package com.connector.global.config;

import com.connector.global.filter.ExceptionHandlerFilter;
import com.connector.global.filter.JwtTokenFilter;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@Order(300)
public class WebSecurityConfig {
    private final JwtTokenFilter jwtTokenFilter;
    private final ExceptionHandlerFilter exceptionHandlerFilter;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.csrf().disable().cors()
                .and()
                .authorizeRequests()
                .antMatchers(HttpMethod.GET, "/api/**").permitAll()
                .antMatchers(HttpMethod.POST, "/api/**").permitAll()
                .antMatchers(HttpMethod.PUT, "/api/**").permitAll()
                .antMatchers(HttpMethod.DELETE, "/api/**").permitAll()
                .antMatchers(
                        "/",
                        "/swagger-ui/**",
                        "/v3/api-docs/**",
                        "/swagger-ui.html")
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .antMatcher("/**")
                .addFilterBefore(jwtTokenFilter, BasicAuthenticationFilter.class)
                .addFilterBefore(exceptionHandlerFilter, JwtTokenFilter.class);

        return http.build();
    }
}

정리

오늘은 WebSecurityConfigurerAdapter 대신 SecurityFilterChain Bean으로 설정하는 방법에 대해 알아봤습니다.

부족한 부분이 많지만 해당 내용은 공부해본 뒤, 다른 포스팅에서 자세히 다뤄보겠습니다.

감사합니다.

출처

 

Deprecate WebSecurityConfigurerAdapter · Issue #10822 · spring-projects/spring-security

With the following issues closed we've added the ability to configure the security of an application without needing the WebSecurityConfigurerAdapter. Related issues: #8804 #8978 #10040 #10138 Back...

github.com

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
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
글 보관함