폼 인증을 위해 사용하는 UsernamePasswordAuthenticationFilter
의 동작 흐름을 파악한다.
스프링 시큐리티가 사용자 인증을 위해 사용하는 기본 필터다
UsernamePasswordAuthenticationFilter
는 AbstractAuthenticationProcessingFilter
를 확장한 클래스로 HttpServletRequest
를 통해 사용자의 이름, 비밀번호를 가져오고 인증을 수행한다.
formLogin api를 통해 폼 로그인 인증 방식 설정을 할 때 UsernamePasswordAuthenticaionFilter
를 생성하며, 로그인 페이지와 로그아웃 페이지 생성을 위한 DefaultLoginPageGeneratingFilter
와 DefaultLogoutGeneratingFilter
도 같이 생성된다.
따라서 폼 로그인 인증 방식을 사용할 때 사용되는 필터는 UsernamePasswordAuthenticationFilter
이다.
우리가 커스텀한 인증 방식을 사용하려고 한다면 AbstractAuthenticationFilter
를 상속한 커스텀 필터 클래스를 작성하여야 하고, AbstractAuthenticationProcessingFilter
클래스의 attemptAuthenticaion
메소드를 override 해야한다.
사용자가 서버에 접근하기 위해 요청을 보낸다.
UsernamePasswordAuthenticationFilter
에서 RequestMatcher
를 통해 현재 요청이 인증이 필요한 요청인지 확인한다.
인증이 필요한 요청인지 확인됐다면 UsernamePasswordAuthenticaionToken
을 생성한다.
3-1. 요청 객체에서 가져온 username, password를 가지고 UsernamePasswordAuthenticaionToken
를 생성한다.
3-2. 생성한 UsernamePasswordAuthenticationToken
을 AuthenticationManger
에게 전달한다.
AuthenticationMangaer
에서 인증 처리를 진행한다.(추후에 자세하게 살펴보자)
4-1. 인증에 성공했을 경우
UsernamePasswordAuthenticationToken
을 다시 생성한다. 이번엔 UserDetails 혹은
User객체와
Authorites`를 포함한 객체를 가지고 생성한다.SessionAuthenticationStrategy
클래스를 통해 새로운 로그인을 알리고 세션 관련 작업들을 수행한다.SecurityContextHolder
를 통해 인증 상태를 유지한다. Authentication
객체를 SecurityContext
에 저장하고, SecurityCotext
를 SecurityContextHolder
에 저장한다.RemeberMeServices
의 loginSuccess
가 호출된다.(Remember-me`가 설정된 경우)ApplicationEventPublisher
를 통해 인증 성공 이벤트를 게시한다. 이 이벤트를 수신하는 Listner를 만들어서 이벤트 발생 시 처리할 작업을 명시할 수도 있다.AuthenticationSuccessHandler
를 호출한다.4-2 인증에 실패했을 경우
SecurityContext
를 모두 삭제한다.RemeberMeServices
의 loginFail
을 호출해서 자동 로그인 정보를 없앤다.AuthenticationFailureHandler
를 호출한다.사용자가 로그인 요청을 수행하면 doFilter
를 호출한다.
인증이 필요한지 아닌지를 판단하고 인증이 필요한 경우라면 attemptAuthenticaion
메소드를 호출해서 인증을 시도한다.
만약 인증이 성공했다면 인증 시도 후에 반환된 객체를 세션에 저장한다.
그리고 인증 성공 핸들러를 실행한다.
만약 인증에 실패했다면 인증 실패 핸들러를 실행한다.
attemptAuthenticaion
은 보통 UsernamePasswordAuthenticaionFilter
같은 AbstractAuthenticaionFilter
를 확장한 구현체에서 override 한다.
인증 성공 객체를 SecurityContext
에 저장하고 securityContextRepository
라는 곳에 SecurityContext
를 저장한다.
여기서 보면 HttpSessionSecurityContextRepository
에 SecurityContext
를 저장하고, 세션 키로 "SPRING_SECURITY_CONTEXT"를 사용하는 것을 짐작할 수 있다.
그리고 마지막으로 지정된 인증 성공 핸들럴르 호출한다.