1. Validation을 활용한 예외처리와 비밀번호 암호화
- Validation과 @RestControllerAdvice 를 사용한 예외처리
- PasswordEncoder를 이용한 비밀번호 암호화
2. github 주소
3. Validation과 @RestControllerAdvice 를 사용한 예외처리
@Getter
public class UserSignupRequest {
@NotBlank @Size(max = 4)
private String username;
@NotBlank @Email
private String email;
@NotBlank @Size(min = 8, max = 20)
private String password;
}
---Controller---
@PostMapping("/signup")
public ResponseEntity<UserSignupResponse> signupUser(
@Valid @RequestBody UserSignupRequest request
){
return ResponseEntity.status(HttpStatus.CREATED).body(userService.save(request));
}
- @RestControllerAdvice을 이용해 IllegalStateException을 한번에 처리
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(IllegalStateException.class)
public ResponseEntity<String> handleIllegalStateException(IllegalStateException e) {
return ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body("요청 오류: " + e.getMessage());
}
}

4. 비밀번호 암호화
- PasswordEncoder를 이용한 비밀번호 암호화
@Component
public class PasswordEncoder {
public String encode(String rawPassword) {
return BCrypt.withDefaults().hashToString(BCrypt.MIN_COST, rawPassword.toCharArray());
}
public boolean matches(String rawPassword, String encodedPassword) {
BCrypt.Result result = BCrypt.verifyer().verify(rawPassword.toCharArray(), encodedPassword);
return result.verified;
}
}
private final PasswordEncoder passwordEncoder;
@Transactional
public UserSignupResponse save(UserSignupRequest request) {
String encodedPW = passwordEncoder.encode(request.getPassword());
User user = new User(
request.getUsername(),
request.getEmail(),
encodedPW
);
User savedUser = userRepository.save(user);
return new UserSignupResponse(
savedUser.getId(),
savedUser.getUsername(),
savedUser.getEmail(),
savedUser.getCreatedAt(),
savedUser.getModifiedAt()
);
}
...
@Transactional(readOnly = true)
public SessionUser login(@Valid UserLoginRequest request) {
User user = userRepository.findByEmail(request.getEmail()).orElseThrow(
() -> new IllegalStateException("없는 유저입니다.")
);
if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
throw new IllegalStateException("비밀번호가 틀립니다.");
}
return new SessionUser(
user.getId(),
user.getUsername(),
user.getEmail()
);
}
5. 트러블 슈팅
- 암호화된 비밀번호를 확인하는 과정에서 맞는 비밀번호를 적어도 예외처리 메시지("비밀번호가 틀립니다.")가 전송
- PasswordEncoder의 matches 메서드를 확인해보니 rawPassword, encodedPassword 순서로 작성하도록 만들어져 있음
- 작성한 코드를 살펴보니 encodedPassword, rawPassword 순서로 작성되어 있어 순서를 바꾸니 정상적으로 작동
if (!passwordEncoder.matches(user.getPassword(), request.getPassword())) {
throw new IllegalStateException("비밀번호가 틀립니다.");
}
if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
throw new IllegalStateException("비밀번호가 틀립니다.");
}