AbstractUserDetailsAuthenticationProvider 클래스의 authenticate 메서드 일부분에 해당한다.그리고 빨간색으로 표시한 부분이 이번 포스팅의 핵심이다. UserDetailsChecker 인터페이스를 구현한 DefaultPreAuthenticationChecks 클래스의 check 메서드를 호출하는 부분이다.
retrieveUser 메서드를 통해 입력한 사용자 이름을 검증하고 additionalAuthenticationChecks 메서드를 통해 입력한 비밀번호를 검증하기 전 수행된다.
UserDetails 객체를 이용하여 사용자의 상태를 확인하는 역할을 수행한다. UserDetails 인터페이스에는 다음과 같은 메서드들이 정의되어 있다.
isAccountNonExpired()
,isAccountNonLocked()
,isEnabled()
이를 통해 사용자가 잠겨있는지, 비활성화되어 있는지, 만료된 계정인지 판단할 수 있다.
여기서 던져지는 LockedException, DisabledException, AccountExpiredException 예외들은 모두 AuthenticationException을 상속받기 때문에, 이를 통합적으로 처리하는 AuthenticationFailureHandler 구현체에서 일괄적으로 핸들링할 수 있다.
우선 사용자가 연속적으로 5번의 비밀번호를 틀렸을 때 하루 동안 계정이 잠기도록 구현하였다.
위와 같이 User 클래스에 lockExpiration 속성을 추가하고 PrincipalDetails 클래스의 isAccountNonLocked 메서드에서 이를 활용하여 사용자의 계정이 잠겨 있는지 여부를 확인할 수 있다.사용자의 계정이 잠금 처리 되어 false 값이 반환될 경우 위의 check 메서드에서 LockedException 예외가 발생하게 될 것이다.
DaoAuthenticationProvider 클래스의 additionalAuthenticationChecks 메서드를 살펴보면 입력한 비밀번호와 실제 저장된 비밀번호를 비교하여 사용자의 인증 여부를 결정하게 된다.비밀번호가 일치하지 않아 인증에 실패하게 될 경우 BadCredentialsException 예외가 발생하는데 AuthenticationFailureHandler 인터페이스를 구현한 클래스에서 이를 처리해줬다.
유저 네임 및 패스워드가 일치하지 않을 경우 모두 BadCredentialsException이 발생한다. 그러나 패스워드가 틀린 경우에만 해당 사용자의 실패한 로그인 시도 횟수를 증가시킨다. 최대 허용 시도 횟수인 5번을 초과하면, 사용자의 계정을 잠금과 관련된 작업을 수행한 후 해당하는 예외 코드를 전달한다.위의 AuthenticationService 클래스의 setAccountLocked 메서드 내용은 다음과 같다.
현재 날짜와 시간으로부터 하루가 지났을 때 계정 잠금이 해제가 될 수 있도록 설정하였다.
로그인 성공 시 로그인 시도 실패 횟수를 초기화 시키도록 구현하였다.