비밀 번호를 찾기 및 변경을 구현하기 위해서 현재 user 가 회원가입할때 적었던 이메일을 통해서 진행해보자.
참고 블로그 : [Spring Boot] 메일 보내기 구현 (Naver) - JavaMailSender (tistory.com)
mail을 보내기 위해서 springboot에서 제공하는
implementation 'org.springframework.boot:spring-boot-starter-mail'
을 추가적으로 gradle에 추가해준다.
spring:
mail:
host: smtp.naver.com
port: 465
username: 아이디@naver.com
password: 비밀번호
properties:
mail.smtp.auth: true
mail.smtp.ssl.enable: true
mail.smtp.ssl.trust: smtp.naver.com
mail.smtp.starttls.enable: true
사용할 네이버메일을 SMTP 사용함으로 설정해준다.
비밀번호 찾기는 UserService에서 처리해야하기 때문에 UserService에서 이 부분을 처리할 예정
@PreAuthorize("isAnonymous()")
@PostMapping("/find")
public String findPw(Model model, UserPasswordFindForm userPasswordFindForm
, BindingResult bindingResult, RedirectAttributes redirectAttributes) {
if (bindingResult.hasErrors()) {
return "/user/find";
}
SiteUser user = userService.getUser(userPasswordFindForm.getUsername());
if (user == null) {
bindingResult.reject("UserNotFound", "일치하는 사용자가 없습니다.");
return "/user/find";
}
if (!user.getEmail().equals(userPasswordFindForm.getEmail())) {
bindingResult.reject("EmailNotCorrect", "이메일이 일치하지않습니다.");
return "/user/find";
}
String tempPw = userService.SetTempPw(user);
userService.sendEmail(user.getEmail(), user.getUsername(), tempPw);
redirectAttributes.addFlashAttribute("successMessage", "임시 비밀번호가 이메일로 전송되엇습니다.");
return "redirect:/user/login";
}
<html layout:decorate="~{layout}">
<main layout:fragment="content" class="container my-3">
<form th:action method="post" th:object="${userPasswordFindForm}" onsubmit="FindPasswordForm__submit(this); return false;">
<div th:replace="~{form_errors :: formErrorsFragment}"></div>
<h2 class="border-bottom py-2">비밀번호 찾기</h2>
<div class="mb-3">
<label lclass="form-label">사용자ID</label>
<input type="text" th:field="*{username}" class="form-control">
</div>
<div class="mb-3">
<label class="form-label">이메일</label>
<input type="text" th:field="*{email}" class="form-control">
</div>
<button type="submit" class="btn btn-primary">비밀번호찾기</button>
</form>
<script th:inline="javascript">
const emailRegExp = new RegExp(/^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/i);
function FindPasswordForm__submit(form) {
form.email.value = form.email.value.trim();
form.username.value = form.username.value.trim();
if (form.username.value.length == 0) {
alert('사용자 아이디를 입력해주세요');
form.username.focus();
return false;
}
// 이메일 정규식 표현 검사
if (!emailRegExp.test(form.email.value)) {
alert('이메일 형식을 지켜야 합니다.');
form.email.focus();
return false;
}
form.submit();
}
</script>
</main>
</html>
javaScript부분은 현재 작성이 제대로 됬는지 확인하기 위한 코드이다.
참고 블로그 : https://taedonn.tistory.com/18
emailRegExp의 경우
@을 기준으로 앞구간이 알파벳 or 숫자 조합인지 확인
@을 기준으로 뒷부분이 알파벳 or 숫자 조합인지 확인
.을 기준으로 뒷붑분이 알파벳 or 숫자 조합으로 이루어져있는지 체크
emailRegExp.test(form.email.value)
비밀번호 변경하는 것의 경우 내 정보에서 비밀번호를 변경할 수 있도록 진행
으로 구성되면 될 것 같다.
<html layout:decorate="~{layout}">
<main layout:fragment="content" class="container my-3">
<form th:action method="post" th:object="${newPwForm}" onsubmit="FindPasswordForm__submit(this); return false;">
<div th:replace="~{form_errors :: formErrorsFragment}"></div>
<h2 class="border-bottom py-2">비밀번호 변경</h2>
<div class="mb-3">
<label lclass="form-label">기존 비밀번호</label>
<input type="text" th:field="*{password}" class="form-control">
</div>
<div class="mb-3">
<label lclass="form-label">새로운 비밀번호</label>
<input type="text" th:field="*{newPassword}" class="form-control">
</div>
<div class="mb-3">
<label lclass="form-label">비밀번호 확인</label>
<input type="text" th:field="*{CheckPassword}" class="form-control">
</div>
<button type="submit" class="btn btn-primary">비밀번호 변경</button>
</form>
passwordEncoder.matches 사용시 주의사항
public abstract boolean matches(CharSequence rawPassword, String encodedPassword)
비밀번호 변경 Controller 코드
@PreAuthorize("isAuthenticated()")
@GetMapping("/changePw")
public String ChangePw(newPwForm newPwForm) {
return "newPw";
}
@PreAuthorize("isAuthenticated()")
@PostMapping("/changePw")
public String ChangePw(@Valid newPwForm newPwForm, BindingResult bindingResult,
Principal principal) {
SiteUser user = userService.getUser(principal.getName());
if (bindingResult.hasErrors()) {
return "newPw";
}
log.info("비밀번호가 맞는지 확인");
if (!userService.isPwMatch(user, newPwForm.getPassword())) {
bindingResult.reject("PasswordNotCorrect", "비밀번호가 일치하지 않습니다.");
return "newPw";
}
log.info("새로운 비밀번호와 비밀번호 확인이 같은지");
if (!newPwForm.getNewPassword().equals(newPwForm.getCheckPassword())) {
bindingResult.reject("NewPasswordInCorrect", "2개의 패스워드가 일치하지않습니다.");
return "newPw";
}
userService.UpdatePw(user, newPwForm.getNewPassword());
return "redirect:/user/me";
}
비밀번호가 맞는지 확인 코드
public boolean isPwMatch(SiteUser user, String pw) {
if (passwordEncoder.matches(pw,user.getPassword())) {
log.info("일치");
return true;
}
return false;
}
비밀번호 변경 코드
@Transactional
public void UpdatePw(SiteUser user, String pw) {
user.updatePW(passwordEncoder.encode(pw));
}
이렇게 하면 비밀번호 변경까지 진행된다.