[Spring Security] 스프링 시큐리티란?

KIM KYUBIN·2023년 1월 6일
0

Spring

목록 보기
1/1

스프링 시큐리티란?

Spring Security는 인증, 인가 및 일반적인 공격에 대한 보호 기능을 제공하는 프레임워크

인증

참이라는 근거가 있는 무언가를 확인하거나 확증하는 행위

인가

리소스에 대한 접근 권한 및 정책을 지정하는 기능

과정

1️⃣ 사용자가 로그인 정보와 함께 인증 요청

2️⃣ AuthenticationFilter가 요청을 가로채고, 로그인 정보를 가지고 UsernamePasswordAuthenticationToken의 인증용 객체 생성

3️⃣ AuthenticationManager의 구현체인 ProviderManager에게 생성한 UsernamePasswordAuthenticationToken을 전달

4️⃣ AuthenticationManager가 등록된 AuthenticationProvider들을 조회해 인증 요구

5️⃣ UserDetailsService에 로그인 정보 전달

6️⃣ DB에서 찾은 사용자 정보인 UserDetails 객체 생성

7️⃣ AuthenticationProvider들은 UserDetails를 전달받고 사용자 정보 비교

8️⃣ 인증이 완료되면 권한 등의 정보를 담은 Authentication 객체 반환

9️⃣ 다시 최초의 AuthenticationFilterAuthentication 객체 반환

🔟 Authentication 객체를 SecurityContext에 저장

✔️ 사용자 정보를 저장한다는 것은 Spring Security가 전통적인 세션-쿠키 기반의 인증 방식을 사용

구조

Filter

Servlet Filter 기반

  • 클라이언트가 애플리케이션에 요청을 보내고 컨테이너는 요청 URI 경로를 기반으로 HttpServletRequest를 처리해야 하는 FilterServlet을 포함하는 FilterChain 생성
    • Spring MVC에서의 ServletDispatcherServlet
  • 1개의 ServletHttpServletRequestHttpServletResponse 처리를 담당한다
    • Filter는 여러 개를 사용할 수 있다, Servlet과 다운스트림 Filter의 실행을 막는다. 이 경우엔 Filter에서 HttpServletResponse를 작성한다
    • 다운스트림에 있는 Servlet과 여러 FilterHttpServletRequestHttpServletResponse를 수정한다
  • Filter는 다운스트림 FilterServlet에만 영향을 미치기 때문에 각 Filter가 호출되는 순서가 매우 중요하다.

DelegatingFilterProxy

스프링은 DelegatingFilterProxy라는 필터 구현을 제공하여 Servlet 컨테이너의 라이프사이클과 ApplicationContext간의 연결을 가능하게 한다.

  • Servlet 컨테이너는 자체 표준을 사용하여 Filter를 등록할 수 있지만 Spring Bean은 알아차리지 못한다.
    • DelegatingFilterProxy는 표준 Servlet 컨테이너 메커니즘을 통해 등록할 수 있지만 모든 작업을 Filter를 구현하는 Spring Bean에 위임
  • ApplicationContext에서 Bean Filter를 찾은 후 호출

FilterChainProxy

스프링 시큐리티가 제공하는 특별한 Filter로, SecurityFilterChain을 통해 여러 Filter 인스턴스로 위임 가능

  • FilterChainProxy는 Bean이기 때문에 DelegatingFilterProxy로 감싸져있다.

SecurityFilterChain

FilterChainProxy가 요청에 사용할 Filter를 선택할 때 사용

  • SecurityFilterChain에 있는 Security Filter는 전형적인 Bean이지만, DelegatingFilterProxy가 아닌 FilterChainProxy로 등록된다.
  • FilterChainProxy을 직접 서블릿 컨테이너에 등록하거나 DelegatingFilterProxy에 등록하면 좋은 점
    • 스프링 시큐리티가 서블릿을 지원할 수 있는 시작점을 제공한다.
      => 서블릿에 스프링 시큐리티를 적용하다가 문제를 겪는다면 FilterChainProxy부터 디버그해 보는 것이 좋다.
    • FilterChainProxy는 스프링 시큐리티의 중심이기 때문에 필수로 여겨지는 작업을 할 수 있다.
    • SecurityFilterChain을 언제 실행해야 할 지 유연하게 결정할 수 있다.
      => 서블릿 컨테이너에서는 URL로만 실행할 Filter들을 결정
      => 그러나, FilterChainProxyRequestMatcher 인터페이스를 사용하면 HttpServletRequest에 있는 어떤 것으로도 실행 여부를 결정할 수 있다.
  • 사용해야 할 SecurityFilterChain을 결정할 때 FilterChainProxy를 사용한다.

  • /api/messages/를 요청하면 SecurityFilterChain0_{0}/api/** 패턴과 제일 먼저 매칭되므로, SecurityFilterChainn_{n}도 일치하긴 하지만 SecurityFilterChain0_{0}만 실행
  • /message/로 요청하면 SecurityFilterChain0_{0}과 매칭되지 않기 때문에 FilterChainProxy는 계속 다른 SecurityFilterChain을 시도
    => 없으면 SecurityFilterChainn_{n}을 실행
  • SecurityFilterChain은 고유하면서 격리된 설정을 가질 수 있다.
    => 스프링 시큐리티가 무시하길 바라면 Filter 0개 설정도 가능

Security Filters

  • 보안 필터는 SecurityFilterChain API를 사용해서 FilterChainProxy에 추가
  • 필터의 순서
    • ChannelProcessingFilter
    • WebAsyncManagerIntegrationFilter
    • SecurityContextPersistenceFilter
    • HeaderWriterFilter
    • CorsFilter
    • CsrfFilter
    • LogoutFilter
    • OAuth2AuthorizationRequestRedirectFilter
    • Saml2WebSsoAuthenticationRequestFilter
    • X509AuthenticationFilter
    • AbstractPreAuthenticatedProcessingFilter
    • CasAuthenticationFilter
    • OAuth2LoginAuthenticationFilter
    • Saml2WebSsoAuthenticationFilter
    • UsernamePasswordAuthenticationFilter
    • OpenIDAuthenticationFilter
    • DefaultLoginPageGeneratingFilter
    • DefaultLogoutPageGeneratingFilter
    • ConcurrentSessionFilter
    • DigestAuthenticationFilter
    • BearerTokenAuthenticationFilter
    • BasicAuthenticationFilter
    • RequestCacheAwareFilter
    • SecurityContextHolderAwareRequestFilter
    • JaasApiIntegrationFilter
    • RememberMeAuthenticationFilter
    • AnonymousAuthenticationFilter
    • OAuth2AuthorizationCodeGrantFilter
    • SessionManagementFilter
    • ExceptionTranslationFilter
    • FilterSecurityInterceptor
    • SwitchUserFilter

Handling Security Exceptions

ExceptionTranslationFilterAccessDeniedException을 해석하고 AuthenticationException을 HTTP 응답으로 바꿔준다.

  • ExceptionTranslationFilterFilterChainProxy에 하나의 Security Filter로 추가

  1. 먼저 ExceptionTranslationFilterFilterChain.doFilter(request, response)를 호출해서 애플리케이션의 나머지 로직을 실행
  2. 인증받지 않은 사용자거나 AuthenticationException이 발생했다면, 인증을 시작
    • SecurityContextHolder를 비운다.
    • RequestCacheHttpServletRequest를 저장
      => 인증에 성공하면 RequestCache로 기존 요청 처리를 이어간다.
    • AuthenticationEntryPoint는 클라이언트에 credential을 요청할 때 사용
  3. 반대로 AccessDeniedException이면, 접근을 거부
    => 거절된 요청은 AccessDeniedHandler에서 처리

애플리케이션에서 AuthenticationExceptionAccessDeniedException을 던지지 않으면 ExceptionTranslationFilter는 동작하지 않는다.

참고

https://godekdls.github.io/Spring%20Security/servletsecuritythebigpicture/
https://docs.spring.io/spring-security/reference/5.6/index.html

profile
상상을 현실로 만들기 위해 노력하는 개발자

0개의 댓글