2022.10.09 - [공부 기록] - 스프링 시큐리티의 우아한 멀티 타입 빌더
스프링 시큐리티를 사용하려면 우리는 WebSecurityConfigurerAdapter 상속받아 확장하는 설정 클래스를 작성하게 된다.
하지만 Spring Security 5.2릴리스부터는 이를 상속받지 않고 람다를 사용하여 HTTP 보안을 구성할 수 있는 DSL에 대한 개선 사항이 포함되었다.
Spring Security Lambda DSL에 대해서는 이 문서를 참고하자.
따라서 이번 포스팅에서는 Deprecated 된 WebSecurityConfigurerAdapter 를 사용하지 않고 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
https://github.com/spring-projects/spring-security/issues/8804
https://docs.spring.io/spring-security/reference/servlet/authorization/authorize-http-requests.html
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")
)
)
;
}
'공부 기록' 카테고리의 다른 글
[JAVA x OPENAPI] 공공데이터포털 특일 정보 OpenAPI 사용하기 - 1 (공공데이터 포털 활용 신청) (0) | 2023.02.13 |
---|---|
[SPRING RETRY] 바퀴를 다시 발명하지 마라 - @Retrayble을 활용한 재시도 전략 (0) | 2023.01.30 |
[SPRING SECURITY]우아한 멀티 타입 빌더 (0) | 2022.10.09 |
[Network] 액세스 회선 (0) | 2022.07.18 |
[Rest Assured] Rest Assured로 Mock과 함께 Controller Unit Test 하기 (0) | 2022.07.09 |
댓글