모르지 않다는 것은 아는것과 다르다.

Spring Security

스프링 시큐리티 아키텍처

채마스 2022. 2. 28. 20:21

Spring Security Architecture

  • Spring Security Architecture 를 그림으로 나타내면 아래와 같다.

  • 요청이 들어오면 서블릿 필터중에 DeligationFilterProxy 라는 필터가 FilterChainProxy를 SecurityFilterAutoConfiguration 이라는 이름의 빈으로 등록 한다.
  • FilterChainProxy 는 요청에 따라 적합한 필터들이 체인형태로 구성된 SecurityFilterChain 을 사용한다. -> 이는 WebSecurity 에 의해서 만들어진다.
  • 이러한 필터들이 사용하는 객체들이 있는다.
    • 인증 -> AuthenticationManager
    • 인가 -> AccessDecisionManager
  • AuthenticationManager
    • 보통 구현체인 ProviderManager 를 많이 사용한다.
    • ProviderManager 는 여러 AuthenticationProvider 를 사용하는데 그 중에서 하나가 DaoAuthenticationProvider 이다.
    • DaoAuthenticationProvider 는 UserDetailsService라는 Dao 인터페이스를 사용해서 인증을 처리한다.
    • 여기서 인증이 성공한다면 그 정보를 SecurityContextHolder 에 넣어서 애플리케이션 전반에 걸처 사용한다.
    • 이렇게 만들어진 정보는 SecurityContextPersistenceFilter 에 의해 사용된다.
  • AccessDecisionManager
    • FilterSecurityInterceptor는 인가를 처리하기 위해서 AccessDecisionManager를 사용한다.
    • AccessDecisionManager가 인가를 처리하는 방법은 3가지가 있는데 그 중에서 하나가 AffirmativeBased 이다.
    • AffirmativeBased 는 AccessDecisionVoter 중에서 WebExpressionVoter 만을 사용한다.
    • WebExpressionVoter 는 SecurityExpressionHandler 를 이용해서 Exception을 처리하는데 계층형한 권한 처리를 위해서 SecurityExpressionHandler 를 커스터 마이징 할 수 있다.

  • 먼저 초기화 과정에서 SecurityConfig 설정파일들에서 정의한 api 들을 바탕으로 filters 을 생성한다.
  • WebSecurity 는 filters 들을 전달받고, filters 를 생성자의 인자로 FilterChainProxy 빈을 springSecurityChain 이라는 이름으로 생성한다.
  • Servlet Filter 중 하나인 DelegatingFilterProxy 는 초기화 될때, springSecurityChain 이름으로 빈을 찾는데 그것이 FilterChainProxy 이다.
  • DelegatingFilterProxy 는 FilterChainProxy 에게 요청을 위임한다.
  • 여기까지가 초기화 과정이고, 이후로 인증과 인가에 관련된 사용자의 요청이 전달된다.
  • 사용자의 최초 인증 (폼 인증)
    • SecurityContextPersistenceFilter -> UsernamePasswordAuthenticationFilter -> SessionManagementFilter
  • 로그인하고 리소스 접근
    • SecurityContextPersistenceFilter -> ExceptionTranslationFilter -> FilterSecurityInterceptor





Authentication Flow

  • 먼저 클라이언트가 폼 인증을 요청한다.
  • UsernamePasswordAuthenticationFilter 는 사용자의 요청을 받아서 아이디와 패스워드를 저장할 수 있는 Authentication 을 생성하고 AuthenticationManager에게 인증처리를 맡긴다.
  • AuthenticationManager 는 인증의 전반적인 관리하지만 실제로 인증역할을 하지 않고 AuthenticationProvider에 위임한다.
  • AuthenticationProvider 는 UserDeatilsService 의 loadUserByUsername 메소드에 username(userId) 를 넘기면서, UserDeatilsService 에게 User 객체를 요구한다.
  • UserDetailsService 는 유저 객체를 DB 에서 조회해서 UserDetails 타입으로 반환해 준다.
    • DB 에 존재하지 않는다면 UserNameNotFoundException이 호출되어 예외가 발생한다.
  • AuthenticationProvider 는 UserDetailsService 에게 받은 UserDetails 값의 Id, Password 값을 비교해서 인증이 성공한다면 Authentication (UserDetails + Authorities) 객체를 생성하고, AuthenticationManager 에게 전달한다.
  • 최종적으로 인증결과를 담은 Authentication 는 다시 UsernamePasswordAuthenticationFilter에게 전달하고 SecurirtyContext에 저장한다.





Authorization

  • Authorization 는 무엇이 허가 되었는지를 증명하는 것이다.
  • 아래의 그림처럼 인증이 된 후 인가를 처리한다.

  • 스프링 시큐리티가 지원하는 권한계층은 아래와 같다.

  • 위와 같이 웹, 서비스, 도메인 계층에서 권한을 검증 할 수 있다.




REFERENCES

  • 백기선님의 스프링 시큐리티
  • 정수원님의 스프링 시큐리티