Spring Security는 인증, 인가 및 일반적인 공격에 대한 보호 기능을 제공하는 프레임워크
참이라는 근거가 있는 무언가를 확인하거나 확증하는 행위
리소스에 대한 접근 권한 및 정책을 지정하는 기능
1️⃣ 사용자가 로그인 정보와 함께 인증 요청
2️⃣ AuthenticationFilter
가 요청을 가로채고, 로그인 정보를 가지고 UsernamePasswordAuthenticationToken
의 인증용 객체 생성
3️⃣ AuthenticationManager
의 구현체인 ProviderManager
에게 생성한 UsernamePasswordAuthenticationToken
을 전달
4️⃣ AuthenticationManager
가 등록된 AuthenticationProvider
들을 조회해 인증 요구
5️⃣ UserDetailsService
에 로그인 정보 전달
6️⃣ DB에서 찾은 사용자 정보인 UserDetails
객체 생성
7️⃣ AuthenticationProvider
들은 UserDetails
를 전달받고 사용자 정보 비교
8️⃣ 인증이 완료되면 권한 등의 정보를 담은 Authentication
객체 반환
9️⃣ 다시 최초의 AuthenticationFilter
에 Authentication
객체 반환
🔟 Authentication
객체를 SecurityContext
에 저장
✔️ 사용자 정보를 저장한다는 것은 Spring Security가 전통적인 세션-쿠키 기반의 인증 방식을 사용
Servlet Filter 기반
HttpServletRequest
를 처리해야 하는 Filter
및 Servlet
을 포함하는 FilterChain
생성Servlet
은 DispatcherServlet
Servlet
이 HttpServletRequest
와 HttpServletResponse
처리를 담당한다Filter
는 여러 개를 사용할 수 있다, Servlet
과 다운스트림 Filter
의 실행을 막는다. 이 경우엔 Filter
에서 HttpServletResponse
를 작성한다Servlet
과 여러 Filter
로 HttpServletRequest
나 HttpServletResponse
를 수정한다Filter
는 다운스트림 Filter
와 Servlet
에만 영향을 미치기 때문에 각 Filter
가 호출되는 순서가 매우 중요하다.
스프링은
DelegatingFilterProxy
라는 필터 구현을 제공하여Servlet
컨테이너의 라이프사이클과ApplicationContext
간의 연결을 가능하게 한다.
Servlet
컨테이너는 자체 표준을 사용하여 Filter
를 등록할 수 있지만 Spring Bean
은 알아차리지 못한다.DelegatingFilterProxy
는 표준 Servlet
컨테이너 메커니즘을 통해 등록할 수 있지만 모든 작업을 Filter
를 구현하는 Spring Bean
에 위임ApplicationContext
에서 Bean Filter를 찾은 후 호출
스프링 시큐리티가 제공하는 특별한
Filter
로,SecurityFilterChain
을 통해 여러Filter
인스턴스로 위임 가능
FilterChainProxy
는 Bean이기 때문에 DelegatingFilterProxy
로 감싸져있다.
FilterChainProxy
가 요청에 사용할Filter
를 선택할 때 사용
SecurityFilterChain
에 있는 Security Filter
는 전형적인 Bean이지만, DelegatingFilterProxy
가 아닌 FilterChainProxy
로 등록된다.FilterChainProxy
을 직접 서블릿 컨테이너에 등록하거나 DelegatingFilterProxy
에 등록하면 좋은 점FilterChainProxy
부터 디버그해 보는 것이 좋다.FilterChainProxy
는 스프링 시큐리티의 중심이기 때문에 필수로 여겨지는 작업을 할 수 있다.SecurityFilterChain
을 언제 실행해야 할 지 유연하게 결정할 수 있다.Filter
들을 결정FilterChainProxy
는 RequestMatcher
인터페이스를 사용하면 HttpServletRequest
에 있는 어떤 것으로도 실행 여부를 결정할 수 있다.SecurityFilterChain
을 결정할 때 FilterChainProxy
를 사용한다./api/messages/
를 요청하면 SecurityFilterChain
의 /api/**
패턴과 제일 먼저 매칭되므로, SecurityFilterChain
도 일치하긴 하지만 SecurityFilterChain
만 실행/message/
로 요청하면 SecurityFilterChain
과 매칭되지 않기 때문에 FilterChainProxy
는 계속 다른 SecurityFilterChain
을 시도SecurityFilterChain
을 실행SecurityFilterChain
은 고유하면서 격리된 설정을 가질 수 있다.Filter
0개 설정도 가능SecurityFilterChain
API를 사용해서 FilterChainProxy
에 추가
ExceptionTranslationFilter
는AccessDeniedException
을 해석하고AuthenticationException
을 HTTP 응답으로 바꿔준다.
ExceptionTranslationFilter
는 FilterChainProxy
에 하나의 Security Filter로 추가ExceptionTranslationFilter
는 FilterChain.doFilter(request, response)
를 호출해서 애플리케이션의 나머지 로직을 실행AuthenticationException
이 발생했다면, 인증을 시작SecurityContextHolder
를 비운다.RequestCache
에 HttpServletRequest
를 저장RequestCache
로 기존 요청 처리를 이어간다.AuthenticationEntryPoint
는 클라이언트에 credential을 요청할 때 사용AccessDeniedException
이면, 접근을 거부AccessDeniedHandler
에서 처리애플리케이션에서
AuthenticationException
나AccessDeniedException
을 던지지 않으면ExceptionTranslationFilter
는 동작하지 않는다.
https://godekdls.github.io/Spring%20Security/servletsecuritythebigpicture/
https://docs.spring.io/spring-security/reference/5.6/index.html