Spring Security란?
스프링 시큐리티는 스프링 기반의 애플리케이션의 보안(인증, 권한, 인가 등)을 담당하는 스프링 하위 프레임워크이다. Spring Security는 인증과 권한에 대한 부분을 Filter 흐름에 따라 처리한다. 그리고 보안과 관련된 많은 옵션을 제공해주기 때문에 개발자 입장에서는 일일이 보안관련 로직을 작성하지 않아도 된다는 장점이 있다.
Architecture
- 사용자는 Form을 통해 로그인 정보를 입력하고 인증 요청을 보낸다.
- AuthenticationFilter는 HttpServletRequest에서 사용자가 보낸 아이디와 패스워드를 인터셉트해서 넘어온 로그인 정보의 유효성 검사를 한다. HttpSerlvetRequest에서 꺼낸 사용자 정보를 인증용 객체(UsernamePasswordAuthenticationToken)로 만든 후, 실제로 로그인 정보 인증을 담당할 AuthenticationManager에게 위임한다.
- AuthenticationFilter에게 인증용 객체인 UsernamePasswordAuthenticationToken을 전달받는다.
- 실제 인증을 할 AuthenticationProvider에게 UsernamePasswordAuthenticationToken을 다시 전달한다.
- DB는 UserDetailsService에게 사용자 아이디를 넘겨주고 DB에서 인증에 사용할 사용자 정보를 UserDetails 객체로 전달받는다.
- AuthenticationProvider는 UserDetails 객체를 전달받은 이후 실제 사용자의 입력정보와 UserDetails 객체를 가지고 인증을 시도한다.
- 8~10 인증이 완료되면 사용자 정보를 가진 Authentication 객체를 SecurityContextHolder에 저장한다. 인증 성공 여부에 따라 성공 시에는 AuthenticationSuccessHandler, 실패 시에는 AuthenticationFailurHandler 핸들러를 실행한다.
인증(Authorization)과 인가(Authentication)
- 인증(Authorization) : 해당 사용자가 누구인지 확인하는 절차, 회원가입/로그인 과정
- 인가(Authentication) : 해당 사용자가 어떤 리소스에 접근할 수 있는지, 어떤 동작을 수행할 수 있는지 권한을 검증하는 절차
Spring Security는 인증 절차를 거친 후 인가 절차를 진행하며 인가 과정에서 해당 리소스에 대한 접근 권한이 있는지 확인한다.
Spring Security는 이러한 인증과 인가를 위해 Principal을 아이디로, Credential을 비밀번호로 사용하는 Credential 기반의 인증방식을 사용하게 된다.
- Principal(접근 주체) : 보호받는 Resource에 접근하는 대상
- Credential(비밀번호) : Resource에 접근하는 대상의 비밀번호
Spring Security 주요 모듈
SecurityContextHolder, SecurityContext, Authentication
이 세 가지 클래스는 Spring Security의 주요 컴포넌트로 각 컴포넌트의 관계를 간단히 표현하면 다음과 같다.
사용자 정보를 넣고 실제 가입된 사용자인지 체크한 후 인증에 성공하면 사용자의 Principal과 Credential 정보를 Authentication에 담는다.
그 후 Spring Security에서 Authentication을 SecurityContext에 보관하게 된다.
이 SecurityContext를 SecurityContextHolder에 담아 보관하게 된다.
Spring Security의 인증 처리
- username과 password를 조합해서 UsernamePasswordAuthenticationToken을 만든다. UsernamePasswordAuthenticationToken은 검증을 위해 AuthenticationManager로 전달된다.
- AuthenticationManager는 인증에 성공하면 Authentication 객체를 리턴한다.
- Authentication은 SecurityContextHolder.getContext().setAuthentication()를 set한다.
Security.ContextHolder.getContext().getAuthentication().getPrincipal();
참고한 블로그에서 이 구문만 보고 어떻게 외워서 쓸 수 있을까, 라는 생각을 했다고 하는데 확실히 그림을 그리고 보면서 이해하니까 왜 이렇게 되는지 이해가 됐다.
Spring Security Filter Chain
Spring Security Filter는 A Filter의 일을 수행하고, B Filter의 일을 수행하는 A -> B -> C Filter ... 의 Chain 형식으로 이루어져 있다.
아래 그림과 같이 한 요청에 대해 다음과 같은 Filter들이 순차적(위->아래)으로 일을 수행한다.
필터들이 순차적으로 요청되면서 doFilter 메소드가 수행된다.
Spring Security에서 제공하는 FormLogin을 사용한다면 FROM_LOGIN_FILTER 이름의 UsernamePasswordAuthenticationFilter 클래스에서 인증절차가 이루어진다. UsernamePasswordAuthenticationFilter는 추상클래스인 AbstractAuthenticationProcessingFilter를 상속하고 있다.
참고 사이트
https://mangkyu.tistory.com/76