✅ 패스워드 수정

Yuri Lee·2020년 11월 13일
0

패스워드 변경

패스워드 변경

  • 패스워드 탭 활성화.
  • 새 패스워드와 새 패스워드 확인의 값이 일치해야 한다.
  • 패스워드 인코딩 할 것!
  • 둘 다 최소 8자에서 최대 50자 사이.
  • 사용자 정보를 변경하는 작업
    - 서비스로 위임해서 트랜잭션 안에서 처리해야 한다.
    - 또는 Detached 상태의 객체를 변경한 다음 Repositoiry의 save를 호출해서 상태
    변경 내역을 적용 할 것(Merge)
  • passwordForm 을 처리할 때 initBinder 사용하기
  • passwordEncoder 를 설정해줘야 함.

PassworForm

새 패스워드를 두번 다 같은 것을 입력했는지 확인하자. 두개의 값을 가지고 있는 PassworForm을 만든다.

PassworForm.java

package com.goodmoim.settings;

import lombok.Data;
import org.hibernate.validator.constraints.Length;

@Data
public class PasswordForm {

    @Length(min = 8, max = 50)
    private String newPassword;

    @Length(min = 8, max = 50)
    private String newPasswordConfirm;
}

이 폼을 Validation 할때 길이를 확인할 수 있게 끔 길이를 설정해준다.

validator 를 만들어보자. 두개의 값이 동일한지 확인해보도록 한다.

PasswordFormValidator.java

package com.goodmoim.settings;

import org.springframework.validation.Errors;
import org.springframework.validation.Validator;

public class PasswordFormValidator implements Validator {
    @Override
    public boolean supports(Class<?> clazz) {
        return PasswordForm.class.isAssignableFrom(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
        PasswordForm passwordForm = (PasswordForm)target;

        if (!passwordForm.getNewPassword().equals(passwordForm.getNewPasswordConfirm())) {
            errors.rejectValue("newPassword", "wrong.value", "입력한 새 패스워드가 일치하지 않습니다.");
        }

    }
}

Validator 를 implements 하면 두개의 메서드를 구현해야 한다.

  • supports 메서드: 어떤 타입의 폼 객체를 검증할 것인가 명시해줘야 한다. PasswordForm.class 에 할당가능한 타입이면 검증을 하겠다.
  • validate 메서드: target 객체가 PasswordForm 가 된다. 두개의 값을 비교해준다. 다르면 errors에 에러를 날려준다.

Validator 는 빈으로 등록할 필요는 없다. 다른 빈을 사용할 게 없기 때문에!

initBinder?

@initBinder 란 Spring Validator를 사용 시 @Valid annotation으로 검증이 필요한 객체를 가져오기 전에 수행할 method를 지정해주는 annotation이다.

form Validation 할때 추가로 사용할 Validator를 어떻게 등록해야 할까? initBinder 를 사용해서 등록할 수 있다. (AccountController에 활용한 적이 있음. 내 머리속의 지우개 😅)

SettingsController.java

    @InitBinder("passwordForm")
    public void initBinder(WebDataBinder webDataBinder) {
        webDataBinder.addValidators(new PasswordFormValidator());
    }

passwordForm을 처리할 때 webDataBinder 에다가 넣어줄 수 있다.

@GetMapping(SETTINGS_PASSWORD_URL)

SettingsController.java

   @GetMapping(SETTINGS_PASSWORD_URL)
    public String updatePasswordForm(@CurrentUser Account account, Model model) {
        model.addAttribute(account);
        model.addAttribute(new PasswordForm());
        return SETTINGS_PASSWORD_VIEW_NAME;
    }

PasswordForm을 넣어준다. 그리고 뷰를 리턴해준다. 그럼 form을 보여줄 수 있다.

@PostMapping(SETTINGS_PASSWORD_URL)

    @PostMapping(SETTINGS_PASSWORD_URL)
    public String updatePassword(@CurrentUser Account account, @Valid PasswordForm passwordForm, Errors errors,
                                  Model model, RedirectAttributes attributes) {
        if (errors.hasErrors()) {
            model.addAttribute(account);
            return SETTINGS_PASSWORD_VIEW_NAME;
        }

        accountService.updatePassword(account, passwordForm.getNewPassword());
        attributes.addFlashAttribute("message", "패스워드를 변경했습니다.");
        return "redirect:" + SETTINGS_PASSWORD_URL;
    }

현재 업데이트를 해야 하는 사용자, 현재 접속하고 있는 사용자의 비밀번호를 업데이트 하는 것이므로 현재 사용자를 가져와야 한다. 그 다음에 Valid를 사용해서 바인딩하고 Validation 하면서 바인딩 받은 모델 에트리뷰트를 파라미터로 등록해주고 발생하는 에러들을 받을 수 있는 errors가 필요하다. 잘 되지 않았다면 model 에다가 account를 다시 넣어주고 뷰를 넣어줘야 하므로 model이 있어야 한다. 그리고 잘 등록했으면 메시지를 보여줄 수 있도록 RedirectAttributes 를 사용한다.

public void updatePassword(Account account, String newPassword) {
        account.setPassword(passwordEncoder.encode(newPassword));
        accountRepository.save(account);
		
}

account.setPassword(newPassword);

를 사용하면 안된다. 인코딩되지 않은 password 자체가 저장될 것이다. (raw) 따라서 반드시 passwordEncoder로 인코더를 해줘야 한다. account에 있는 정보를 새로운 password로 변경해주는데, 이 객체는 detached 상태이다. 그래서 명시적으로 상태 변경을 해줘야 한다. (accountRepository.save(account);)

패스워드 변경 뷰

password.html

<script th:replace="fragments.html :: form-validation"></script>

needs-validation 사용하기

클라이언트에서 validation 한번 한 다음에, 서버사이드로 올 것이다. 서버 사이드에서도 validation 해야 한다. 클라이언트에 있는 validation은 최선의 노력일 뿐 .. 뚫릴 수 있는 값이므로 믿어선 안된다. 어디까지나 옵션이다.


출처 : 인프런 백기선님의 스프링과 JPA 기반 웹 애플리케이션 개발
https://mia-dahae.tistory.com/23

profile
Step by step goes a long way ✨

0개의 댓글