목록
HeaderWriterFilter
CsrfFilter
LogoutFilter
UsernamePasswordAuthenticationFilter
응답헤더에 시큐리티 관련 헤더를 추가해주는 필터이다.
다음과 같은 HeaderWriter 를 사용하여 시큐리티 관련 헤더를 추가해준다.
XContentTypeOptionsHeaderWriter: 마임 타입 스니핑 방어.
XXssProtectionHeaderWriter: 브라우저에 내장된 XSS 필터 적용.
CacheControlHeadersWriter: 캐시 히스토리 취약점 방어.
HstsHeaderWriter: HTTPS로만 소통하도록 강제.
XFrameOptionsHeaderWriter: clickjacking 방어.
스프링 시큐리티를 적용하고 ResponseHeader 를 살펴보면,
헤더에 다양한 정보를 넘겨 보안을 컨트롤 할 수 있게하는 모습을 볼 수 있다.
위 헤더에는 HstsHeaderWriter 가 추가해주는 헤더는 포함되어있지 않은데,
학습하는 동안 Https을 사용하지 않아, Https 설정을 하지 않았기 때문이다.
이름에서 알 수 있듯이 CSRF attack 을 방어하기 위한 filter 이다.
우선 CSRF attack 에 대해 잠시 설명하자면, 사용자를 기만해 원치 않는 요청을 임의대로 만들어서 보내는 악의적인 공격이다.
다음과 같은 flow 로 공격이 이루어진다.
이러한 Csrf 공격을 방지하기 위해서는 일반적으로 domain origin 이라는 정책을 사용하는데,
쉽게 말해 A 라는 사이트에서 Csrf attack 을 방지하기위해 A 사이트 domain 에서 온 요청아니라면 리소스를 주지않는 방법으로 Csrf 공격을 방어할 수 있다.
하지만, 필요에 의해서 CORS(Cross-Origin Resource Sharing) 가 필요한 경우도 있고 이 경우에는 CSRF에 비교적 취약해질 우려가 있다.
스프링의 CsrfFilter 는 CSRFtoken 을 활용하여 CSRF attack 을 방어한다. 사용자의 요청이 CsrfFilter 를 거쳐서 가는데 CsrfFilter 에서는 사용자의 CSRFtoken 값을 확인해 토큰이 없거나, 다르다면 요청을 거부해버린다. 기본전략은 요청한 세션에 토큰이 없다면 토큰을 생성해 주고, DefaultRequiresCsrfMatcher 에서 설정되어 있는 "GET", "HEAD", "TRACE", "OPTIONS" 을 제외한 요청에는 토큰값 비교하여 요청을 진행할지 안할지를 결정하게 된다.
이름에서 유추할 수 있듯이, 로그아웃 요청이 들어왔을 때 동작하는 필터이다.
로그아웃 POST 요청이 들어오면,
디버거로 잡아놓은 if 절이 true로 잡혀 로그아웃 핸들러들이 작업을 수행하게 된다.
private final LogoutHandler handler;
private final LogoutSuccessHandler logoutSuccessHandler;
다음 두 핸들러가 시행되는데 우선 LogoutHandler 가 수행되는데, 이 핸들러는 composite 타입으로 기본 설정으로는,
다음과 같은 핸들러들이 사용된다.
LogOutHandler가 수행된 이후에 LogoutSuccessHandler 가 로그아웃 성공후에 수행되어 로그아웃 이후 redirection 할 곳으로 보내주는데
기본적으로는 로그인페이지로 redirect 시켜준다.
사용자 인증을 처리해주는 필터인 이 필터는,
사용자가 폼에 입력한 username 과 password 로 UsernamePasswordAuthenticationToken 을 만들고, 토큰을 들고 AuthenticationManager 를 사용해 인증을 처리하는데, AuthenticationManager 의 기본구현체는 ProviderManager 이고, providerManager 는 여러개의 AuthenticationProvider 에게 인증을 위임하고 폼 기반의 인증의 경우 DaoAuthenticationProvider 가 인증을 처리하게 된다.
DaoAuthenticationProvider 는 UserDetailsService 의 loadByUsername() 을 사용해 사용자가 입력한 username 정보를 바탕으로 DB에서 데이터를 가져와 (id, pw, role) 사용자가 입력한 비밀번호와 DB에서 가져온 비밀번호가 일치하면 인증된 Authentication (UsernamePasswordAuthenticationToken) 을 SecurityContextHolder에 세팅하는 과정이 처리된다.
*참고: 이 포스팅은 백기선님의 스프링시큐리티 강의를 듣고, 제 나름대로 다시 공부하고 정리한 포스팅 입니다. 만약, 조금 더 자세한 내용을 듣고 싶으시다면 이곳의 강의를 참고해보시기 바랍니다