@ModelAttribute에 BeanValidation 적용

기존에 로그인 Validator 적용을 한 바 있다. 하지만, BeanValidation을 배운 이후에, 로그인, 회원가입에서 BeanValidation을 부분적으로 적용이 가능할 것 같아 보였다.

BeanValidation 적용

아이디, 비밀번호의 유무, 길이 정도는 BeanValidation 적용이 가능하다.

Dto

@Data
public class LoginUserDto {
    @NotBlank
    @Size(min = 5)
    private String username;

    @NotBlank
    @Size(min = 5)
    private String password;
}

Controller

@PostMapping("/login")
public String login(HttpSession session, @Validated @ModelAttribute("user") LoginUserDto user, BindingResult bindingResult) {

    log.debug("objectName={}", bindingResult.getObjectName()); // loginUserDto로 나오고 있었다. @ModelAttribute("user")로 해결
    log.debug("target={}", bindingResult.getTarget()); // 정상적으로 LoginUserDto 인스턴스를 찾아옴.

    log.debug("Input User DTO: {}", user);

    /* 검증 실행 */
    loginValidator.validate(user, bindingResult);

    /* 검증에 에러가 발견되면, 폼을 보여줌. */
    if (bindingResult.hasErrors()) {
        log.debug("errors={}", bindingResult);
        return "home/login";
    }

    /* 검증이 끝나면, 컨트롤러에서 로그인 처리 */
    userService.login(session, user);

    /* 로그인 후에 홈으로 리다이렉트 */
    return "redirect:/";

}

Validator

    @Override
    public void validate(Object target, Errors errors) {
        LoginUserDto user = (LoginUserDto) target;

        String password = user.getPassword();

        // 로그인 검증
        User foundUser = getFoundUser(user);

        if (rejectAuthentication(foundUser, password)) {
            errors.reject(LOGIN_ERROR, null, null);
        }

    }

    private User getFoundUser(LoginUserDto user) {
        return userService.findByUsername(user.getUsername());
    }

    /**
     * 받은 User 객체와 password 파라미터가 일치하는지 확인하고 실패할 시 결과 반환
     *
     * @param user     : User 객체
     * @param password : password
     * @return : 일치하다면 true, 일치하지 않으면 false
     */
    private boolean rejectAuthentication(User user, String password) {

        if (user == null) {
            return true;
        }

        return !user.getPassword().equals(password);

    }

정리

정리하면, 흐름은 다음과 같다.

  • BeanValidation으로 검증이 가능한 영역은 BeanValidation으로 검증
  • 복잡한 검증은 Validator 사용하기

댓글

개발자  김철준

백엔드 개발자 김철준의 블로그입니다.

주요 프로젝트