
폼 인증을 위해 사용하는 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"를 사용하는 것을 짐작할 수 있다.
그리고 마지막으로 지정된 인증 성공 핸들럴르 호출한다.