1. Spring Security란?

Spring 기반의 애플리케이션 보안(권한,인증 , 인가 등을) 담당하는 Spring 하위 프레임워크 입니다.

Spring Security는 Filter의 흐름에 따라 처리합니다. Interceptor와 Filter로 인증과 권한에 대한 부분을 대부분 처리합니다. Filter의 경우 Dispatcher Servlet으로 가기전에 적용되며, Interceptor는 Dispatcher와 Controller사이에 적영되어, 적용시기가 다르다는 점이 있습니다. Interceptor로도 Security와 같이 동작하게 할 수 있지만 Spring에서는 Security사용을 적극 권장하고 있습니다.


2. 인증과 인가

인증(Authentication): 해당 사용자가 본인이 맞는지 확인

인가(Authorization): 인증된 사용자가 요청을한 자원에 접근 가능한지 확인

 

3. Authentication Architecture

 

하나씩 살펴보겠습니다.

1. UsernamePasswordAuthenticationFilter (AuthenticationFilter의 구현체라고 생각하면 되겠습니다.)

  • 해당 객체는 AbstractAuthenticationProcessingFilter를 상속받았습니다. 
  • 밑에 로직은 로그인 요청이 왔을 때 실행됩니다. 요청의 username과 password를 기반으로 토큰을 생성하여 AuthenticationManager에게 넘겨줍니다.
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
      throws AuthenticationException {
   if (this.postOnly && !request.getMethod().equals("POST")) {
      throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
   }
   String username = obtainUsername(request);
   username = (username != null) ? username : "";
   username = username.trim();
   String password = obtainPassword(request);
   password = (password != null) ? password : "";
   UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
   // Allow subclasses to set the "details" property
   setDetails(request, authRequest);
   return this.getAuthenticationManager().authenticate(authRequest);
}

2. AuthenticationProvider

  • AuthenticationManager의 구현체로 실제 인증 부분을 처리합니다. 위의 UsernamePasswordAuthenticationFilter에서 보낸 Authentication이 들어오며, 인증을 진행하고, 인증이 완료되면 다시 보내게 됩니다.

3. UserDetailsService

  • UserDetails를 반환 하는 메소드 한 개를 가지고 있습니다. 해당 메소드를 UserRepository를 주입받아 DB에 저장되어 있는 username과 password를 비교할 수 있습니다.
public interface UserDetailsService {
   UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}

4. UserDetails

  • 직접 만든 User Entity에 상속받아 사용합니다. 해당 객체는 UsernamePasswordAuthenticationToken을 생성하는데 이용됩니다. 위 과정을 역순으로 다시 돌아가 SecurityContextHolder에 저장됩니다.

5. SecurityContextHolder

  • 해당 객체는 보안의 세부 정보를 포함하여 응용프로그램의 현재 보안 컨텍스트에 대한 정보가 저장됩니다.

6. SecurityContext

  • Authentication을 보관하는 역할을 하여, Authentication을 꺼내올 수 있습니다.

7. Authentication

  • 현재 접근하는 주체의 정보와 권한을 담은 인터페이스입니다. 
  • Credentials= username, Principal= password를 의미합니다.
  • getAuthorities(): 권한을 가져올 수 있습니다. 
public interface Authentication extends Principal, Serializable {


   Collection<? extends GrantedAuthority> getAuthorities();

   Object getCredentials();

   Object getDetails();

   Object getPrincipal();

   boolean isAuthenticated();

   void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;

}

지금까지 Spring Security에 전반적인 플로우와 개념을 알아봤습니다. 다음으로는 직접 구현체들을 Custom해보겠습니다. 감사합니다.