728x90
원리
SpringSecurity의 PasswordEncoder를 사용하여 password를 bCript 등으로 인코딩 하면, 디코딩이 불가능하다.
따라서 디코딩을 통한 password 검증은 불가능하며, 대안으로 password를 비교 검증할 수 있는 메서드가 있다.
boolean TF = passwordEncoder.matches(입력한_Password, DB에_저장된_Password);
* 자세한 설명은 아래 참고 링크를 확인
더보기
참고 링크 : stella6767님의 벨로그
DaoAuthenticationProvider
컨트롤러에서 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 메서드를 활용해 암호화된 비번 검증할 수 있다.
비번을 암호화하면 매번 다른 랜덤키로 인코딩 되기 때문에, 인코더 객체의 matches 함수를 활용해 검증해야한다.
=> 아래의 코드를 필요에 따라 사용하면 된다.
코드
: 필자의 경우, PasswordEncoder를 DI하기 위해 Service 계층에서 구현하였다.
1. 비밀번호 검증만 하는 로직
@Transactional(readOnly=true)
public void verifyPassword(String password, Long memberId) {
Member member = new Member().verifyMember(memberRepository.findById(memberId));
if(!passwordEncoder.matches(password, member.getPassword())) {
throw new BusinessLogicException(ExceptionCode.NOT_EXACT_PASSWORD);
}
}
2. 비밀번호 검증 및 수정하는 로직
/**
* password 일치 여부 조회 메소드
* @param memberId
*/
@Transactional
public void verifyPassword(String password, Long memberId) {
Member member = new Member().verifyMember(memberRepository.findById(memberId));
if(passwordEncoder.matches(password, member.getPassword())) {
// 새로운 비밀번호를 encoding하여 변경해주는 로직. 같은 비밀번호가 입력되어도 새로 인코딩하여 업데이트 해주는 역할.
String updatedPassword = passwordEncoder.encode(password);
member.modifyPassword(updatedPassword);
} else {
throw new BusinessLogicException(ExceptionCode.NOT_EXACT_PASSWORD);
}
}
3. 회원 정보 수정 시 비밀번호를 같이 수정할 수 있는 로직(이때, 비밀번호는 필수 입력이다)
/**
* 들어오는 값에 따라, 다음의 Patch 요청을 개별적으로 관리 가능합니다. (null이 아닐경우 수정되는 방식 미적용)
* 1. 회원 정보 변경 가능
* 2. 회원 상태 변경 가능
* 비즈니스 로직은 Member Entity 내에서 처리
* @param memberId 추후 JWT에서 추출 예정
*/
@Transactional
public void modifyMember(Member member, Long memberId) {
Member existMember = new Member().verifyMember(memberRepository.findById(memberId));
Optional.ofNullable(member.getPassword()).ifPresent(pw -> existMember.modifyPassword(passwordEncoder.encode(pw))); // 비밀번호는 필수항목? 혹은 비밀번호 변경은 따로 분리?
Optional.ofNullable(member.getNickname()).ifPresent(existMember::modifyNickname);
Optional.ofNullable(member.getProfile()).ifPresent(existMember::modifyProfile); // 현재 profile의 경우 단순 URI상태. 추후 파일로 변경 예정
Optional.ofNullable(member.getMemberStatus()).ifPresent(existMember::modifyMemberStatus);
memberRepository.save(existMember);
}
728x90
'Java & Spring > Spring' 카테고리의 다른 글
| [OAuth2.0] Google 로그인 (백엔드 테스트 버젼) (2) | 2023.02.06 |
|---|---|
| [OAuth2.0] 이론 (0) | 2023.02.06 |
| [OAuth2.0] 카카오 로그인 (프론트엔드 브라우저 연동 버젼) (0) | 2023.02.03 |
| [OAuth2.0] 카카오 로그인 (백엔드 테스팅 버젼) (0) | 2023.01.30 |
| [Spring] SpringSecurity - JwtTokenizer (1) | 2023.01.26 |