문제가 발생한 코드는 다음과 같습니다.
@Override
public boolean join(MemberRequestDto dto) {
if (existsById(dto.getId())) {
return false;
} if (existsByNickname(dto.getNickname())) {
return false;
} if (existsByTel(dto.getTel())) {
return false;
}
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
Member member = Member.builder()
.id(dto.getId())
.password(encoder.encode(dto.getPassword()))
.name(dto.getName())
.nickname(dto.getNickname())
.gender(dto.getBirth())
.birth(dto.getBirth())
.tel(dto.getTel())
.smoke(dto.getSmoke())
.address(dto.getAddress())
.build();
repository.save(member);
return true;
}
위의 코드는 회원가입 서비스 로직입니다. 적절한 검증을 거친 후 멤버 엔티티를 DB에 저장하는 것을 볼 수 있습니다. 이 때 비밀번호는 BCryptPasswordEncoder
를 통해 암호화를 시킨 상태에서 저장을 합니다.
다음은 해당 엔티티가 DB에 저장이 된 모습입니다.
이후 로그인을 시도해보았습니다.
위의 사진과 같이 에러가 발생했습니다. 😢😢😢
스프링 시큐리티 5.0.0 버전 이후부터는 인코딩된 패스워드에 어떤 PasswordEncoder
를 사용했는지 접두사를 붙여주어야 합니다!!
이러한 형태에요 → {id}ENCODED_PASSWORD
만약 BCryptPasswordEncoder
를 사용하였다면 {bcrypt}ENCODED_PASSWORD
,
NoOpPasswordEncoder
를 사용하였다면 {noop}ENCODED_PASSWORD
와 같은 형태가 되겠죠.
이를 해결하기 위해서 단순하게 인코딩된 패스워드에 {bcrypt}
를 붙여주는 방법도 있겠지만 스프링 시큐리티에서 제공해주는 아주 깔끔한 방법이 있습니다!
바로 PasswordEncoderFactories
에요.
이 클래스에는 createDelegatingPasswordEncoder()
라는 메서드가 있는데 PasswordEncoder
를 생성해줍니다. 그리고 여기서 생성된 인코더를 사용하면 비밀번호를 암호화시킨 후 인코더의 ID를 자동으로 붙여줍니다!
아래 코드는 제가 사용한 방법이에요.
@Override
public boolean join(MemberRequestDto dto) {
if (existsById(dto.getId())) {
return false;
} if (existsByNickname(dto.getNickname())) {
return false;
} if (existsByTel(dto.getTel())) {
return false;
}
// 이 부분이 수정되었습니다!!
PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
Member member = Member.builder()
.id(dto.getId())
.password(encoder.encode(dto.getPassword()))
.name(dto.getName())
.nickname(dto.getNickname())
.gender(dto.getBirth())
.birth(dto.getBirth())
.tel(dto.getTel())
.smoke(dto.getSmoke())
.address(dto.getAddress())
.build();
repository.save(member);
return true;
}
그리고 결과를 보여드릴게요.
위와 같이 암호화 된 비밀번호 앞에 {bcrypt}
라는 인코더 ID값이 들어갔어요!
그리고 로그인도 성공해서 HTTP 헤더의 Authorization
에 JWT값이 잘 들어가는 부분도 확인할 수 있었습니다!