feat : CustomFilter 및 관련 설정, 주석 추가

This commit is contained in:
banjjoknim
2022-03-27 02:46:27 +09:00
parent 9ff7046f38
commit 7bfd6ed19c
4 changed files with 105 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
package com.banjjoknim.playground.config.filter
import javax.servlet.Filter
import javax.servlet.FilterChain
import javax.servlet.ServletRequest
import javax.servlet.ServletResponse
/**
* @see javax.servlet.Filter
* @see com.banjjoknim.playground.config.security.JwtSecurityConfiguration
*/
class CustomFilter1 : Filter {
override fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
println("필터1")
chain.doFilter(request, response) // 필터체인에 request, response 를 등록해주어야 한다. 그렇지 않으면 현재 필터가 진행되고 이 이후의 필터들은 더이상 동작하지 않게 된다.
}
}
class CustomFilter2 : Filter {
override fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
println("필터2")
chain.doFilter(request, response) // 필터체인에 request, response 를 등록해주어야 한다. 그렇지 않으면 현재 필터가 진행되고 이 이후의 필터들은 더이상 동작하지 않게 된다.
}
}
class CustomFilter3 : Filter {
override fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
println("필터3")
chain.doFilter(request, response) // 필터체인에 request, response 를 등록해주어야 한다. 그렇지 않으면 현재 필터가 진행되고 이 이후의 필터들은 더이상 동작하지 않게 된다.
}
}

View File

@@ -0,0 +1,60 @@
package com.banjjoknim.playground.config.filter
import org.springframework.boot.web.servlet.FilterRegistrationBean
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
/**
* 기본 설정시 Spring Security 는 일련의 Servlet Filter Chain(FilterChainProxy 라는 클래스로 등록되어 있다. 하나의 Filter 로 등록 되어있지만 내부적으로는 여러개의 Filter 가 동작하고 있다) 을 자동으로 구성한다(web tier 에 있는 Spring Security 는 Servlet Filter 에 기반을 두고 있다).
*
* 일반적인 웹 환경에서 브라우저가 서버에게 요청을 보내게 되면, DispatcherServlet(Controller)가 요청을 받기 이전에 많은 ServletFilter(서블릿 필터)를 거치게 된다.
*
* Spring Security 역시 Servlet Filter 로써 작동하며, 인증 또는 권한과 관련한 처리를 진행하게 된다.
*
* 본래 Servlet Filter 는 WAS(Web Application Server)에서 담당하는데 Spring 은 이 Servlet Filter 들을 직접 관리하기 위해서 DelegatingFilterProxy 를 web.xml 에 설정한다.
*
* 이를 통해 Spring 에서 설정된 Servlet Filter Bean 객체를 거치게 된다.
*
* 여기서는 스프링 시큐리티 필터체인에 필터를 추가하는 대신, 직접 필터를 만들어서 사용한다.
*
* 굳이 Security Filter Chain 에 필터를 추가할 필요가 없고, 이렇게 따로 만들어서 사용해도 된다.
*
* Filter 를 Bean 으로 등록해놓으면, 요청이 들어왔을 때 등록된 Filter 가 동작하게 된다.
*
* 이때, Security Filter Chain 이 우리가 직접 만든 Filter 보다 먼저 동작한다.
*
* 만약 우리가 만든 Filter 를 원하는 위치에서 동작하도록 하고 싶다면 원하는 위치에 Filter 를 추가하면 된다.
*
* 이때, Security Filter Chain 의 순서는 com.banjjoknim.playground.config.filter.SecurityFilterChain.png 이미지를 참고하자.
*
* - Filter type의 Bean에는 @Order 어노테이션으로 순서를 정할 수 있다.
* - FilterRegistrationBean을 이용하여 순서를 정할 수 있다
*
* ```kotlin
* http.addFilterBefore(MySecurityFilter3(), SecurityContextPersistenceFilter::class.java)
* ```
*
* @see org.springframework.boot.web.servlet.FilterRegistrationBean
* @see com.banjjoknim.playground.config.security.JwtSecurityConfiguration
* @see org.springframework.web.filter.DelegatingFilterProxy
* @see org.springframework.security.web.FilterChainProxy
*/
@Configuration
class FilterConfiguration {
@Bean
fun customFilter1(): FilterRegistrationBean<CustomFilter1> {
val bean = FilterRegistrationBean(CustomFilter1())
bean.addUrlPatterns("/*") // 모든 요청에 대해 필터가 동작하도록 설정한다.
bean.order = 0 // 필터의 순서를 정할 수 있는데, 낮은 번호가 필터중에서 가장 먼저 실행된다.
return bean
}
@Bean
fun customFilter2(): FilterRegistrationBean<CustomFilter2> {
val bean = FilterRegistrationBean(CustomFilter2())
bean.addUrlPatterns("/*") // 모든 요청에 대해 필터가 동작하도록 설정한다.
bean.order = 1 // 필터의 순서를 정할 수 있는데, 낮은 번호가 필터중에서 가장 먼저 실행된다.
return bean
}
}

View File

@@ -1,9 +1,11 @@
package com.banjjoknim.playground.config.security
import com.banjjoknim.playground.config.filter.CustomFilter3
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.config.http.SessionCreationPolicy
import org.springframework.security.web.context.SecurityContextPersistenceFilter
import org.springframework.web.filter.CorsFilter
/**
@@ -11,6 +13,11 @@ import org.springframework.web.filter.CorsFilter
*
* 토큰 기반(JWT)을 사용한 설정에서는 기본이며, 상태가 없는 서버를 만들 때 사용한다.
*
* ```kotlin
* Spring Filter Chain 에 존재하는 BasicAuthenticationFilter의 동작 이전에 MySecurityFilter1 을 추가한다. 하지만 반드시 SecurityFilter 에 Filter 를 추가할 필요는 없다.
*
* http.addFilterBefore(MySecurityFilter1(), BasicAuthenticationFilter::class.java)
* ```
* @see org.springframework.security.config.http.SessionCreationPolicy
*/
@EnableWebSecurity // 시큐리티 활성화 -> 시큐리티 설정을 기본 스프링 필터체인에 등록한다.
@@ -18,6 +25,13 @@ class JwtSecurityConfiguration(
private val corsFilter: CorsFilter // CorsConfiguration 에서 Bean 으로 등록해준 CorsFilter 를 Spring 으로부터 DI 받는다.
) : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
// Spring Filter Chain 에 존재하는 BasicAuthenticationFilter의 동작 이전에 MySecurityFilter1 을 추가한다. 하지만 반드시 SecurityFilter 에 Filter 를 추가할 필요는 없다.
// http.addFilterBefore(MySecurityFilter1(), BasicAuthenticationFilter::class.java)
// 우리가 원하는 위치에 Filter 를 등록한다. 만약 Spring Security Filter 보다도 먼저 실행되게 하고 싶다면 SecurityContextPersistenceFilter 보다 먼저 실행되도록 아래처럼 등록해주면 된다.
http.addFilterBefore(CustomFilter3(), SecurityContextPersistenceFilter::class.java)
http.csrf().disable()
// 기본적으로 웹은 STATELESS 인데, STATEFUL 처럼 쓰기 위해서 세션과 쿠키를 만든다. 이때, 그걸(세션과 쿠키) 사용하지 않도록 설정하는 것이다.
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 세션을 사용하지 않겠다는 설정. 토큰 기반에서는 기본 설정이다. 상태가 없는 서버를 만든다.