본문 바로가기
스프링과 JPA 기반 웹 어플리케이션 개발/1부 (개발환경, 회원가입, 로그인, 계정설정)

26. 패스워드 수정

by Backchus 2020. 4. 21.

패스워드 변경 뷰

 

패스워드 변경

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

 

새로운 패스워드를 입력받기위한 PasswordForm DTO를 생성

package me.weekbelt.studyolle.settings;

@NoArgsConstructor
@Data
public class PasswordForm {

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

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

 

패스워드와 패스워드 확인이 같은지 체크하기위해 Validator생성

package me.weekbelt.studyolle.settings;

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

    @Override
    public void validate(Object target, Errors errors) {
        PasswordForm passwordForm = (PasswordForm) target;
        if (!passwordForm.getNewPassword().equals(passwordForm.getNewPasswordConfirm())) {
            errors.rejectValue("newPassword", "wrong.value", "입력한 새 패스워드가 일치하지 않습니다.");
        }
    }
}

 

SettingsController에 Validator등록

package me.weekbelt.studyolle.settings;

@RequiredArgsConstructor
@Controller
public class SettingsController {

    @InitBinder("passwordForm")
    public void initBinder(WebDataBinder webDataBinder) {
        webDataBinder.addValidators(new PasswordFormValidator());
    }
    
    // 기존 코드 .........
}

 

패스워드 수정 폼의 GET 요청과 수정의 POST요청 구현

package me.weekbelt.studyolle.settings;

@RequiredArgsConstructor
@Controller
public class SettingsController {

    // 기존 코드 .....

    @GetMapping("/settings/password")
    public String updatePasswordForm(@CurrentUser Account account, Model model) {
        model.addAttribute(account);
        model.addAttribute(new PasswordForm());
        return "settings/password";
    }

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

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

 

SettingsService에서 패스워드 수정을 처리하기위해 updatePassword메소드 구현

package me.weekbelt.studyolle.account;


@Transactional
@RequiredArgsConstructor
@Service
public class AccountService implements UserDetailsService {

    // 기존 코드 ........

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

 

패스워드 수정 폼인 /settings/password.html 작성

<!DOCTYPE html>
<html lang="en"
      xmlns:th="http://www.thymeleaf.org">
<!--head-->
<head th:replace="fragments.html::head"></head>

<body class="bg-light">
<!--네비게이션 바-->
<div th:replace="fragments.html::main-nav"></div>

<div class="container">
    <div class="row mt-5 justify-content-center">
        <div class="col-2">
            <div th:replace="fragments.html :: settings-menu(currentMenu='password')"></div>
        </div>
        <div class="col-8">
            <div th:if="${message}" class="alert alert-info alert-dismissible fade show mt-3" role="alert">
                <span th:text="${message}">메시지</span>
                <button type="button" class="close" data-dismiss="alert" aria-label="Close">
                    <span aria-hidden="true">x</span>
                </button>
            </div>
            <div class="row">
                <h2 class="col-sm-12">패스워드 변경</h2>
            </div>
            <div class="row mt-3">
                <form class="needs-validation col-12" action="#"
                      th:action="@{/settings/password}" th:object="${passwordForm}" method="post" novalidate>
                    <div class="form-group">
                        <label for="newPassword">새 패스워드</label>
                        <input id="newPassword" type="password" th:field="*{newPassword}" class="form-control"
                               aria-describedby="newPasswordHelp" required min="8" max="50">
                        <small id="newPasswordHelp" class="form-text text-muted">
                            새 패스워드를 입력하세요.
                        </small>
                        <small class="invalid-feedback">패스워드를 입력하세요.</small>
                        <small class="form-text text-danger" th:if="${#fields.hasErrors('newPassword')}" th:errors="*{newPassword}">
                            New Password Error
                        </small>
                    </div>
                    <div class="form-group">
                        <label for="newPasswordConfirm">새 패스워드 확인</label>
                        <input id="newPasswordConfirm" type="password" th:field="*{newPasswordConfirm}" class="form-control"
                               aria-describedby="newPasswordConfirmHelp" required min="8" max="50">
                        <small id="newPasswordConfirmHelp" class="form-text text-muted">
                            새 패스워드를 다시 한번 입력하세요.
                        </small>
                        <small class="invalid-feedback">새 패스워드를 다시 입력하세요.</small>
                        <small class="form-text text-danger" th:if="${#fields.hasErrors('newPasswordConfirm')}" th:errors="*{newPasswordConfirm}">
                            New Password Error
                        </small>
                    </div>

                    <div class="form-group">
                        <button class="btn btn-outline-primary" type="submit" aria-describedby="submitHelp">패스워드 변경하기기
                       </button>
                    </div>
                </form>
            </div>
        </div>
    </div>
    <!-- footer -->
    <div th:replace="fragments.html::footer"></div>
</div>
<script th:replace="fragments.html::form-validation"></script>
</body>
</html>

 

 

참고: https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-JPA-%EC%9B%B9%EC%95%B1#

 

스프링과 JPA 기반 웹 애플리케이션 개발 - 인프런

이 강좌에서 여러분은 실제로 운영 중인 서비스를 스프링, JPA 그리고 타임리프를 비롯한 여러 자바 기반의 여러 오픈 소스 기술을 사용하여 웹 애플리케이션을 개발하는 과정을 학습할 수 있습니다. 이 강좌를 충분히 학습한다면 여러분 만의 웹 서비스를 만들거나 취직에 도움이 될만한 포트폴리오를 만들 수 있을 겁니다. 활용 웹 개발 프레임워크 및 라이브러리 Java Spring Spring Boot Spring Data JPA Thymeleaf 온라인 강의 스

www.inflearn.com