스프링 시큐리티 예제를 보며 개발하다 보면 UserDetailsService
인터페이스의 loadUserByUsername(String username)
을 구현해서 사용자 정보를 DB에서 조회하고 반환한다.
하지만 비밀번호를 체크하는 코드는 없다. 그래도 잘못된 비밀번호를 입력하면 로그인에 실패한다.
내가 작성한 코드에는 없지만 어디에선가 비밀 번호 체크를 하고 있는 것이다. 비밀 번호는 어디에서 체크할까?
컨트롤러에서 AuthenticationManager.authenticate(Authentication)
을 호출하면 스프링 시큐리티에 내장된 AuthenticationProvider의 authenticate()
메서드가 호출되는데, 이 중에서 DaoAuthenticationProvider.additionalAuthenticationChekcs(UserDetails, UsernamePasswordAuthenticationToken)
메서드에 다음과 같은 코드가 있다.
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"));
}`
시큐리티를 사용 중, 회원사 비번 수정 기능을 부여하는데 있어서 기존 비밀번호를 한 번 더 테스트해야 될 필요가 있었다. 하지만, 비번을 암호화하면 매번 다른 랜덤키로 인코딩 되기 때문에, 기존 방식으로 검증은 불가능하고, 인코더 객체의 matches 함수를 활용해, 검증할 수 있었다.
@Transactional
public Integer memberUpdatePassword(MemberReqDto reqDto) {
Member member = memberMapper.findByMemberId(reqDto.getId());
Integer result;
//매번 다른 랜덤키를 부여하기 때문에 떠로 디코딩 작업필요
if (bCryptPasswordEncoder.matches(reqDto.getCheck_member_password(), member.getMember_password())) {
log.info("일치합니다.");
String updatePassword = bCryptPasswordEncoder.encode(reqDto.getMember_password());
result = memberMapper.updateMemberPassword(reqDto.getId(), updatePassword);
} else {
log.info("불일치합니다.");
result = 0;
}
return result;
}
https://github.com/HomoEfficio/dev-tips/blob/master/Spring Security의 사용자 비밀번호 검사.md
딱 필요한 부분을 올바르게 정리해주셔서 감사합니다 ㅎㅎ 잘 보고 배워갑니다!