Spring Security

Kyunghwan Ko·2022년 11월 30일
0

Spring Boot

목록 보기
1/2
post-thumbnail

Spring Security란?

  • 인증 및 보안 관련 로직 제공
  • 리소스 별 권한 제어 및 접근 제어

Spring Security는 Spring Application 개발시에 보안을 적용하기 위해 사용하는 보안 프레임워크 이다. Spring Security는 웹 보안을 위하여 인증 및 보안 관련 로직을 제공한다. 특히 Spring Security의 가장 중요한 기능 중 하나는 리소스 별 권한 제어이다. 따라서 Spring Security에서는 설정을 통해 리소스 별 권한 제어, 리소스별 인증 로직 구현을 쉽게 구현할 수 있다.

Spring Security 구조

Spring Security는 Filter 한 종류로 사용자의 요청이 Servlet Application에 도착하기 전에 사용자의 요청을 먼저 받아 사용자의 요청의 권한 및 보안 점검을 시행한다. Spring Seucity는 어떤 식으로 동작할까?

Filter

HTTP 요청을 Servlet이 받아 Controller에 HTTP 요청을 전달해준다. 그러나 때로는 Servlet에 HTTP 요청에 전처리(pre-processing)를 해주거나 사용자에게 전달하는 응답에 후처리(post-processing)를 해줘야할 때가 있다. 예를 들면 모든 요청과 응답에 대한 로깅, 요청의 보안 검사가 있겠다. 이런 전처리 후처리를 담당하는 컴포넌트를 Filter라고 한다.

위의 그림은 Filter의 동작 방식을 나타낸 그림이다. 여러 Filter는 1 -> 2 -> 3 -> Servlet -> 3 -> 2 -> 1순서대로 처리가 되는 것을 볼 수 있다. 이를 Filter Chain이라 합니다. Filter들을 순서대로 거치면서 요청의 전처리 후처리가 되는 것이다.

Security Filter Chain

Spring Security는 앞서 설명한 Filter를 이용하여 보안기능을 수행한다다. 일반적인 Filter의 경우 모든 요청에 모든 Filter가 동작한다. 그러나 Spring Security는 사용자가 접근하는 리소스에 따라서 보안 및 인증 처리를 하기 때문에 일반적인 Filter가 아닌 FilterChainProxy를 구현하여 사용한다.

위의 구조는 Spring Security의 Filter 구조이다. DelegatingFilterProxy는 Spring Bean을 Filter로 등록할 수 있게 해주는 Proxy 객체이다. Spring Security는 SecurityFilterChain이라는 FilterChainProxy를 Filter로 등록하는데, 이는 리소스 별로 다른 FilterChain을 등록하게 만들어 주는 역할을 한다. Spring Security는 이러한 구조를 통해서 사용자가 접근하려는 리소스 별로 보안 로직을 다르게 하는 유연한 구조를 가지고 있다.

우리는 이제 리소스별로 어떠한 Filter를 적용할 것인지 선언만 해주면 Spring Security가 그에 맞는 보안을 수행하게 할 수 있다. Spring Security에서 사전에 구현해 놓은 Filter를 적용하여도 되고, 아니면 커스텀 Filter를 만들어 적용할 수도 있다.

Spring Filter Chain 리스트

위의 그림은 Spring Security에서 기본적으로 제공하는 Filter의 동작 순서와 리스트다.

  • SecurityContextPersistentFilter:
    SecurityContextRepository에서 SecurityContext를 가져와서 SecurityContextHolder에 주입하거나 반대로 저장하는 역할을 합니다.
  • LogoutFilter:
    logout 요청을 감시하며, 요청시 인증 주체(Principal)를 로그아웃 시킵니다
  • UsernamePasswordAuthenticationFilter:
    login 요청을 감시하며, 인증 과정을 진행합니다.
  • DefaultLoginPageGenerationFilter:
    사용자가 별도의 로그인 페이지를 구현하지 않은 경우, 스프링에서 기본적으로 설정한 로그인 페이지로 넘어가게 합니다.
  • BasicAuthenticationFilter:
    HTTP 요청의 (BASIC)인증 헤더를 처리하여 결과를 SecurityContextHolder에 저장합니다.
  • RememberMeAuthenticationFilter:
    SecurityContext에 인증(Authentication) 객체가 있는지 확인하고 RememberMeServices를 구현한 객체 요청이 있을 경우,
    RememberMe를 인증 토큰으로 컨텍스트에 주입합니다.
  • AnonymousAuthenticationFilter:
    이 필터가 호출되는 시점까지 사용자 정보가 인증되지 않았다면 익명 사용자로 취급합니다.
  • SessionManagementFilter:
    요청이 시작된 이후 인증된 사용자인지 확인하고, 인증된 사용자일 경우 SessionAuthenticationStrategy를 호출하여 세션 고정 보호 매커니즘을 활성화 하거나 여러 동시 로그인을 확인하는 것과 같은 세션 관련 활동을 수행합니다.
  • ExceptionTranslationFilter:
    필터체인 내에서 발생되는 모든 예외를 처리합니다.
  • FilterSecurityInterceptor:
    AccessDecisionManager로 권한부여처리를 위임하고 HTTP 리소스의 보안 처리를 수행합니다.

Spring Secuirty 인증 구조

  1. 사용자가 입력한 사용자 정보를 가지고 인증을 요청한다.(Request)
  2. AuthenticationFilter가 이를 가로채 UsernamePasswordAuthenticationToken(인증용 객체)를 생성한다
  3. 필터는 요청을 처리하고 AuthenticationManager의 구현체 ProviderManager에 Authentication과
    UsernamePasswordAuthenticationToken을 전달한다.
  4. AuthenticationManager는 검증을 위해 AuthenticationProvider에게 Authentication과
    UsernamePasswordAuthenticationToken을 전달한다.
  5. 이제 DB에 담긴 사용자 인증정보와 비교하기 위해 UserDetailsService에 사용자 정보를 넘겨준다.
  6. DB에서 찾은 사용자 정보인 UserDetails 객체를 만든다.
  7. AuthenticationProvider는 UserDetails를 넘겨받고 비교한다.
  8. 인증이 완료되면 권한과 사용자 정보를 담은 Authentication 객체가 반환된다.
  9. AuthenticationFilter까지 Authentication정보를 전달한다.
  10. Authentication을 SecurityContext에 저장한다.

Authentication정보는 결국 SecurityContextHolder 세션 영역에 있는 SecurityContext에 Authentication 객체를 저장한다. 세션에 사용자 정보를 저장한다는 것은 전통적인 세션-쿠키 기반의 인증 방식을 사용한다는 것을 의미한다.

profile
부족한 부분을 인지하는 것부터가 배움의 시작이다.

0개의 댓글