스프링 시큐리티 form login을 구현하다가 문득 든 의문인데 UserDetailsService
에서 loadUserByUsername(String username)
에서는 아이디로만 DB에서 조회하고 사용자 정보를 반환해주기만 하지 비밀번호를 검증하는 것은 전혀 보이지 않는다.
그렇다면 어디서 비밀번호를 검증해서 로그인이 잘되도록 해주는 것일까?
나와같은 의문을 가진 사람이 있어서 이걸 참고해서 코드 까보면서 찾아봤다.
위의 링크를 보면(위의 링크 코드를 퍼왔다)
String presentedPassword = authentication.getCredentials().toString();
if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
logger.debug("Authentication failed: password does not match stored value");
throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials",
"Bad credentials"));
}
비밀번호 체크는 DaoAuthenticationProvider
라는 곳에서 대신 처리를 해주는데, passwordEncoder.matches()
를 통해서 처리를 해주고 있는 것을 볼 수 있다.
또한 PasswordEncoder
도 DaoAuthenticationProvider
에 필드로 들어있는 것을 확인할 수 있다(이건 직접 코드를 까보자)
그렇다면 저 인코더는 어떻게 설정해둔 것일까?
보통 시큐리티 설정은 WebSecurityConfigurerAdapter
를 상속한 Config 클래스를 만들어서 사용하는데, 부모 클래스의 메소드 중 protected void configure(AuthenticationManagerBuilder auth)
를 아래와 같이 오버라이드하여 사용한 게 포인트였다.
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(principalDetailsService).passwordEncoder(passwordEncoder());
}
AuthenticationManagerBuilder
를 통해 userDetailsService
를 설정해두고 거기에 passwordEncoder에 내가 사용한 인코더를 매개변수로 넣어두면
AbstracDaoAuthenticationConfigurer
라는 추상클래스가 DaoAuthenticationProvider
의 passwordEncoder를 set 해준다.
public C passwordEncoder(PasswordEncoder passwordEncoder) {
this.provider.setPasswordEncoder(passwordEncoder);
return (C) this;
}
그 후 DaoAuthenticationProvider가 받은 PasswordEncoder로 비밀번호를 대조해주던 것!
찾아보니 DaoAuthenticationProvider를 사용하는 것 말고 AuthenticationProvider
인터페이스를 구현해서 커스터마이징하여 사용하는 것도 가능한 것 같다.
궁금했던 점 완전히 해결하고 갑니다 감사해요 🙏