본문 바로가기

IT/Spring

[Spring Boot] Spring Security의 동작

Spring Security 란?

Spring Security는 스프링 기반의 어플리케이션 보안을 담당하는 프레임워크이다.

Spring Security를 사용하면 사용자 인증, 권한, 보안처리를 간단하지만 강력하게 구현 할 수 있다. 

Filter 기반으로 동작하기 때문에 Spring MVC와 분리되어 동작한다. 

Spring Security를 이해하기 위해서는 먼저 보안관련 용어를 숙지해야 한다.

접근 주체(Principal)
보안 시스템이 작동되고 있는 애플리케이션에 접근하는 유저
인증(Authentication)
접근한 유저를 식별하고, 애플리케이션에 접근할 수 있는지 검사
인가(Authorize)
인증된 유저가 애플리케이션의 기능을 이용할 수 있는지 검사

SecurityFilterChain

일반적으로 브라우저가 서버에 데이터를 요청하면 DispatcherServlet에 전달되기 이전에 여러 ServletFilter를 거친다.

이때 Spring Security에서 등록했었던 Filter를 이용해 사용자 보안 관련된 처리를 진행한다.

Spring Security와 관련된 Filter들은 연결된 여러 Filter들로 구성되어있다. 이 때문에 Chain이라는 표현을 사용하고 있다.

SecurityFilterChain 상세

 

SecurityContextPersistenceFilter
SecurityContextRepository에서 SecurityContext를 가져와 유저 Authentication에 접근 할 수 있게 한다.
LogoutFilter
로그아웃 요청을 처리한다.
UsernamePasswordAuthenticationFilter 
ID와 Password를 사용하는 Form 기반 유저 인증을 처리한다. 
DefaultLoginPageGeneratingFilter
커스텀 로그인 페이지를 지정하지 않았을 경우 Default Login Page를 반환한다.
AnonymousAuthenticationFilter
이 필터가 호출되는 시점까지 사용자 정보가 인증되지 않았다면 익명 사용자 토큰을 반환한다.
ExceptionTranslationFilter
필터 체인 내에서 발생되는 모든 예외(AccessDeniedException, AuthenticationException...)를 처리한다.
FilterSecurityInterceptor
권한부여와 관련한 결정을 AccessDecisionManager에게 위임해 권한부여 결정 및 접근 제어를 처리한다.
RequestCacheAwareFilter
로그인 성공 후, 이전 요청 정보를 재구성하기 위해 사용한다.
SessionManagementFilter
로그인 이후 인증된 사용자인지 확인하거나 설정된 Session 메커니즘에 따라 작업을 수행한다. (동시 로그인 확인 등...)
BasicAuthenticationFilter 
HTTP 요청의 인증 헤더를 처리하여 결과를 SecurityContextHolder에 저장한다. (HttpBasic 방식) 
RememberMeAuthenticationFilter
세션이 사라지거나 만료 되더라도 쿠키 또는 DB를 사용하여 저장된 토큰 기반으로 인증을 처리하는 필터

Spring Security 동작

1. AuthenticationFilter (UsernamePasswordAuthenticationFilter)는 사용자의 요청을 가로챈다. 그리고 인증이 필요한 요청이라면 사용자의 JSESSIONID가 Security Context에 있는지 판단한다. 없으면 로그인 페이지로 이동시킨다

로그인 페이지에서 요청이 온 경우라면 로그인 페이지에서 입력받은 username과 password를 이용해 UsernamePasswordAuthenticationToken을 만든다.  그리고 UsernamePasswordAuthenticationToken 정보가 유효한 계정인지 판단하기 위해 AuthenticationManager로 전달한다.


2. AuthenticationManager 인터페이스의 구현체는 ProviderManger이고  AuthencationProvider에게 비밀번호 인증 로직 책임을 넘긴다. (AuthencationProvider는 개발자가 직접 커스텀해서 비밀번호 인증로직을 직접 구현할 수 있다.)

3. AuthencationProvider는 UserDetailsService를 실행해 비밀번호 인증 로직을 처리한다.

UserDetailsService는 DB에 저장된 회원의 비밀번호와 비교해 일치하면 UserDetails 인터페이스를 구현한 객체를 반환하는데, UserDetailsService는 인터페이스이며 UserDetailsService를 구현한 서비스를 직접 개발해야한다.

4. 인증 로직이 완료되면 AuthenticationManager는 Authentication를 반환하며, 결과적으로 SecurityContext에 사용자 인증 정보가 저장된다.

5. 인증 과정이 끝났으면 AuthenticationFilter에게 인증에 대한 성공 유무를 전달하고
성공하면 AuthenticationSuccessHandler를 호출하고 실패하면 AuthenticationFailureHandler를 호출한다.


참조

https://sjh836.tistory.com/165?category=680970

https://okky.kr/article/382738

https://tramyu.github.io/java/spring/spring-security/