톰켓과 같은 WAS를 서블릿 컨테이너라고 부르는데, 이런 웹 애플리케이션(J2EE Application)은 기본적으로 필터와 서블릿으로 구성
Dispatch Servlet
이란 컨트롤러의 메서드에 url을 매핑해서 Web request가 그 메서드를 찾아가도록 하게 해줌
-> 즉 url과 매핑되는 메서드를 실행시켜주는 역할
Filter 란 세션 매칭
or 인코딩
을 마쳐줌
-> 모든 Request에 대해 공통적으로 적용되야 할 것을 filter 단에 위치 시킴
필터는 체인처럼 엮여있기 때문에 필터 체인
이라고도 불리는데, 모든 request 는 이 필터 체인을 반드시 거쳐야만 서블릿 서비스에 도착
시큐리티는 정책에 따라 여러 Security 정책이 공존할 수 있음(Switching 하면서 사용하는 것이 중요)
Spring Security는 DelegatingFilterProxy 라는 필터를 만들어
메인 Filter Chain에 끼워넣고, 그 아래 다시 SecurityFilterChain 그룹을 등록
-> 이를 통해 URL에 따라 적용되는 Filter Chain을 다르게 하는 방법
을 사용
-> 메인 필터를 반드시 통과해야만 서블릿에 들어갈 수 있는 단점을 보완하기 위해서 필터체인 Proxy
를 두었다고 볼 수 있다
web resource
의 경우 패턴을 따르더라도 필터를 무시(ignore)하고 통과시켜주기도 함
WebSecurityConfigurerAdapter
는 Filter chian을 구성하는 Configuration클래스로 해당 클래스의 상속을 통해 Filter Chain을 구성할 수 있다
configure(HttpSecurity http)
를 override하며 filter들을 세팅
@EnableWebSecurity(debug = true) // request가 올 떄마다 어떤 filter를 사용하고 있는지 출력을 해준다.
@EnableGlobalMethodSecurity(prePostEnabled = true) // 사전에 prePost로 권한체크를 하겠다는 설정!!
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// WebSecurityConfigurerAdapter`는 Filter chian을 구성하는 Configuration클래스
@Override
protected void configure(HttpSecurity http) throws Exception {
// HttpSecurity를 설정하는 것이 Filter들을 Setting하는 것이다.
http.authorizeRequests((requests) ->
requests.antMatchers("/").permitAll()
.anyRequest().authenticated()
);
http.formLogin(login->
login.defaultSuccessUrl("/", false));
http.httpBasic();
}
}
각각의 필터는 단일 필터 단일 책임(?) 원칙 처럼, 각기 서로 다른 관심사를 해결
필터는 넣거나 뺄 수 있고 순서를 조절할 수 있다
-> 이때 필터의 순서가 매우 critical 할 수 있기 때문에 기본 필터들은 그 순서가 어느정도 정해져 있다
HeaderWriterFilter
: Request의 Http 해더를 검사하여 header를 추가하거나 빼주는 역할을 한다.CorsFilter
: 허가된 사이트나 클라이언트의 요청인지 검사하는 역할을 한다.CsrfFilter
: Post나 Put과 같이 리소스를 변경하는 요청의 경우 내가 내려보냈던 리소스에서 올라온 요청인지 확인한다.LogoutFilter
: Request가 로그아웃하겠다고 하는것인지 체크한다.UsernamePasswordAuthenticationFilter
: username / password 로 로그인을 하려고 하는지 체크하며, 승인이 되면 Authentication을 부여하고 이동 할 페이지로 이동한다. 인증 실패 또한 처리ConcurrentSessionFilter
: 동시 접속을 허용할지 체크한다.BearerTokenAuthenticationFilter
: Authorization 해더에 Bearer 토큰을 인증해주는 역할을 한다.BasicAuthenticationFilter
: Authorization 해더중에서 Basic 토큰을 인증해주는 역할을 한다.RequestCacheAwareFilter
: request한 내용을(일종의 내역) 다음에 필요할 수 있어서 Cache에 담아주는 역할을 한다. 다음 Request가 오면 이전의 Cache값을 줄 수 있다.SecurityContextHolderAwareRequestFilter
: 보안 관련 Servlet 3 스펙을 지원하기 위한 필터라고 한다.RememberMeAuthenticationFilter
: 아직 Authentication 인증이 안된 경우라면 RememberMe 쿠키를 검사해서 인증 처리해준다.AnonymousAuthenticationFilter
: 앞선 필터를 통해 인증이 아직도 안되었으면 해당 유저는 익명 사용자라고 Authentication을 정해주는 역할을 한다. (Authentication이 Null인 것을 방지!!)SessionManagementFilter
: 서버에서 지정한 세션정책에 맞게 사용자가 사용하고 있는지 검사하는 역할을 한다.ExcpetionTranslationFilter
: 해당 필터 이후에 인증이나 권한 예외가 발생하면 해당 필터가 처리를 해준다.FilterSecurityInterceptor
: 사용자가 요청한 request에 들어가고 결과를 리턴해도 되는 권한(Authorization)이 있는지를 체크한다. 해당 필터에서 권한이 없다는 결과가 나온다면 위의 ExcpetionTranslationFilter필터에서 Exception을 처리해준다 -> Authentication이 있다고 가정
그 밖에 OAuth2 나 Saml2, Cas, X509 등에 관한 필터도 존재함
-> 개발자가 정책에 따라 필터를 만들어 사용하기도 함
WebSecurityConfigurerAdapter을 상속받아 Filter Chain을 만드는 Class위에 @EnableWebSecurity(debug = true)
어노테이션을 붙여주면 현재 실행되는 Security Fiter들을 확인 가능
Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CsrfFilter
LogoutFilter
UsernamePasswordAuthenticationFilter
DefaultLoginPageGeneratingFilter
DefaultLogoutPageGeneratingFilter
BasicAuthenticationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests((requests) ->
requests.antMatchers("/").permitAll()
.anyRequest().authenticated());
http.formLogin();
http.httpBasic();
}
메서드내 코드들을 주석처리 하면 실행되는 필터가 확 줄어든 것을 볼 수 있다
@Override
protected void configure(HttpSecurity http) throws Exception {
...
Http
.headers().disable()
.csrf().disable()
.logout().disable()
.requestCache().disable()
}
위 코드는 특정 필터를 실행시키지 않는 방법
http.antMatcher
를 통해 설정http.antMatcher("/**")
로 하며 /api~~에 대해서 적용을 하고 싶다면 http.antMatcher("/api/**")
와 같이 설정여러 종류의 URL에 대해 여러 Filter
를 만들고 싶다면 SecurityConfig 클래스를 여러개 만들어줘야하며 여러개의 sequrityConfig은 순서가 중요하여 class위에 @Order
annotation을 붙여줘야 함@Order(1) // order가 낮은 것부터 먼저 설정
@EnableWebSecurity(debug = true)
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**"); // 해당 filter가 동작할킬 URL을 설정하려면 antMatcher를 통해 설정해야함
http.authorizeRequests((requests) ->
requests.antMatchers("/").permitAll()
.anyRequest().authenticated()
);
http.formLogin(login->
login.defaultSuccessUrl("/", false));
http.httpBasic();
}
}