본문 바로가기
Security

Spring Security Filter및 DB 인증 암호화 인증과정 설명 (UsernamePasswordAuthenticationFilter)

by Gil Granger 2019. 4. 26.

Spring Security를 적용하게 되면 각 필터를 각 순서에 대한 실행된다.

각각의 필터의 목적은 다르며 실행 요청에 따라 처리를 할수도, 스킵이 될 수도 있다.

먼저 필터의 각 역활부터 보기로 한다.

그 다음에 이글의 주요목적인 로그인에대한 필터 인증 과정을 설명하도록 한다. 

 

Spring Security Filter 설명

 

  1. SecurityContextPersistenceFilter : SecurityContextRepository에서 SecurityContext를 가져오거나 저장하는 역할을 한다. (SecurityContext는 밑에)
  2. LogoutFilter : 설정된 로그아웃 URL로 오는 요청을 감시하며, 해당 유저를 로그아웃 처리
  3. (UsernamePassword)AuthenticationFilter : (아이디와 비밀번호를 사용하는 form 기반 인증) 설정된 로그인 URL로 오는 요청을 감시하며, 유저 인증 처리
    • AuthenticationManager를 통한 인증 실행
    • 인증 성공 시, 얻은 Authentication 객체를 SecurityContext에 저장 후 AuthenticationSuccessHandler 실행
    • 인증 실패 시, AuthenticationFailureHandler 실행
  4. DefaultLoginPageGeneratingFilter : 인증을 위한 로그인폼 URL을 감시한다.
  5. BasicAuthenticationFilter : HTTP 기본 인증 헤더(Basic Authorization)를 감시하여 처리한다.
  6. RequestCacheAwareFilter : 로그인 성공 후, 원래 요청 정보를 재구성하기 위해 사용된다.
  7. SecurityContextHolderAwareRequestFilter : HttpServletRequestWrapper를 상속한 SecurityContextHolderAwareRequestWapper 클래스로 HttpServletRequest 정보를 감싼다. SecurityContextHolderAwareRequestWrapper 클래스는 필터 체인상의 다음 필터들에게 부가정보를 제공한다.
  8. AnonymousAuthenticationFilter : 이 필터가 호출되는 시점까지 사용자 정보가 인증되지 않았다면 인증토큰에 사용자가 익명 사용자로 나타난다.
  9. SessionManagementFilter : 이 필터는 인증된 사용자와 관련된 모든 세션을 추적한다.
  10. ExceptionTranslationFilter : 이 필터는 보호된 요청을 처리하는 중에 발생할 수 있는 예외를 위임하거나 전달하는 역할을 한다.
  11. FilterSecurityInterceptor : 이 필터는 AccessDecisionManager 로 권한부여 처리를 위임함으로써 접근 제어 결정을 쉽게해준다.

 


Spring Security Config DB 인증 설정 (SuccessHandler 및 Login Form 생략)

(authenticationProvider에 대한 역활은 아래에서 확인해 볼 수 있다.)

여기서 확인해야할될 점은 DaoAuthenticationProvider를 설정하는데 암호화 인코딩과 userdetailService를 등록했다는 점이다. 

 

다음은 로그인화면에서 로그인 진행 시(/Login) 인증되는 플로우이다. 

(3. UsernamePasswordAuthenticationFilter)

 

 

 

UsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter

각 필터를 타고 UsernamePasswordAuthenticationFilter에 도달했을때 AbstractAuthenticationProcessingFilter클래스를 통해 로그인 URL인지 확인하고 로그인 요청이 확인 될 시 아이디 패스워드를 가져와서 인증을 위한 객체를 생성한다.

 

 

  • AuthenticationManager에서 Provider를 통한 인증 실행

 

 

ProviderManager

  • parent인  ProviderManager 로드하여 DaoAuthenticationProvider 호출

 

DaoAuthenticationProvider 의 추상 클래스인 AbstractUserDetailsAuthenticationProvider 실행

AbstractUserDetailsAuthenticationProvider에서 추상적인 인증과정 형태를 보여주고 있다.

하나의 템플릿 메소드 디자인 패턴이라고 볼 수 있겠다. (AbstractAuthenticationProcessingFilter도 마찬가지)

 

구체적인 인증과정은 필자가 설정한 DaoAuthenticationProvider로 구현되게 된다.  

 

DaoAuthenticationProvider 

유저아이디를 통해 유저정보를 로드 할수 있도록 UserDetailService를 정의했었다. (SecurityConfig에서 UserDetailsService를 구현한 클래스를 설정했었다.)

 

  • Provider에서 UserDetailService - loadUserByUsername메소드 호출

여기서 user아이디를 통해서 DB에 접근하여 유저정보를 로드하도록 구현하면 된다.

물론 패스워드를 포함하여 UserDetails 형태의 데이터 객체로 로드되어야 한다.

 

DaoAuthenticationProvider 

 

로드한 UserDetails 데이터로 입력한 패스워드와 비교하여 실패시 Excpeiton을 발생시킨다.

 

성공시,

 

  • 인증 성공 시  AuthenticationSuccessHandler 실행

 

 

 

--------------------------------------------------------------------------------------

<추가> 

http 권한 처리 우선순위 

.antMatchers(HttpMethod.POST,"/api/test/test").hasAuthority(ROLE_COMMON)
.antMatchers(""/api/test/**"").hasAuthority(ROLE_PRO)

이렇게 설정하게되면 test/test 에 접근할수 있는 롤은 COMMON이 되고 나머지 test로 시작되는 url 요청은 PRO가 된다.

하지만 

.antMatchers(""/api/test/**"").hasAuthority(ROLE_PRO)
.antMatchers(HttpMethod.POST,"/api/test/test").hasAuthority(ROLE_COMMON)

반대로 하게 되면 각 요청이 다 PRO의 권한을 요구하게 된다.

 

결론 : 먼저 설정한 것이 우선순위를 갖는다는 것을 알 수 있다.

 

 

 

 

참고: https://sjh836.tistory.com/165

댓글