Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

Been_DevStep

Spring Boot - Recover Password 본문

공부/SpringBoot

Spring Boot - Recover Password

JChBeen 2022. 11. 10. 16:31

인증 후에 비밀번호를 입력해서 재설정을 하는 JS코드입니다.

// 인증 후 비밀번호 재설정 버튼
form['passwordUpdate'].addEventListener('click', () => {
    Warning.hide();
    if (form['password'].value === '' || form['passwordCheck'].value === '') {
        Warning.show("비밀번호를 입력해주세요.");
        return;
    }   //비어있는지 확인합니다.

    if (form['password'].value !== form['passwordCheck'].value) {
        Warning.show("비밀번호가 일치하지 않습니다.");
        return;
    }   // 입력한 두 비밀번호가 일치하는지 확인합니다.

    const xhr = new XMLHttpRequest();
    const formData = new FormData;
    formData.append("email", form['email'].value);
    formData.append("password", form['password'].value);
    formData.append("code", form['code'].value);
    formData.append("salt", form['salt'].value);
    // hide되어있는 code와 salt값을 포함한 email, password를 담아서 보냅니다.
    xhr.open('PATCH', './recoverPassword');
    xhr.onreadystatechange = () => {
        if(xhr.readyState === XMLHttpRequest.DONE){
            Cover.hide();
            if(xhr.status >= 200 && xhr.status < 300) {
                const responseObject = JSON.parse(xhr.responseText);
                switch (responseObject['result']) {
                    case 'success' :
                        alert("변경에 성공했습니다.");
                        window.location.href = 'login';
                        break;
                    default:
                        Warning.show("비밀번호 변경에 실패하였습니다.");
                        form['email'].focus();
                        form['email'].select();
                }
            }else  Warning.show('서버와 통신하지 못하였습니다. 잠시 후 다시 시도해 주세요.');
        }
    };xhr.send(formData);
});

Controller 입니다.

@RequestMapping(value = "recoverPassword",
        method = RequestMethod.PATCH,
        produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public String patchRecoverPassword(UserEntity user, EmailAuthEntity emailAuth){
    Enum<?> result = this.memberService.recoverPassword(user, emailAuth);
    JSONObject responseObject = new JSONObject();
    responseObject.put("result", result.name().toLowerCase());

    return responseObject.toString();
}

Service 입니다.

@Transactional
public Enum<? extends IResult> recoverPassword(UserEntity user, EmailAuthEntity emailAuth) {
    // email, code, salt 를통해서 EmailAuthEntity 에서 일치하는 레코드를 가져옵니다.
    EmailAuthEntity existingEmailAuth = this.memberMapper.selectEmailAuthByEmailCodeSalt(
                  emailAuth.getEmail(), emailAuth.getCode(), emailAuth.getSalt());

    //만약 가져온 값이 null 이라면 인증이 제대로 되지 않았기 때문에 failure
    //가져온 값의 isExpired()가 false 라면 failure
    if (existingEmailAuth == null || !existingEmailAuth.isExpired()) return CommonResult.FAILURE;

    //인증된 existingEmailAuth 의 'email' 을 통해서 User 에서 해당 레코드를 가져옵니다.
    UserEntity existingUser = this.memberMapper.selectUserByEmail(existingEmailAuth.getEmail());

    // existingUser 이 null 이라면 값이 없는 것이기 때문에 FAILURE
    if (existingUser == null) return CommonResult.FAILURE;

    //입력 받은 password 를 sha-512 를 통해 값을 수정하고 set 합니다.
    existingUser.setPassword(CryptoUtils.hashSha512(user.getPassword()));

    //update 를 했는데 반환되는 값이 0이라면 제대로 적용되지 않았기 때문에 FAILURE
    if (this.memberMapper.updateUser(existingUser) == 0)
        return CommonResult.FAILURE;

    return CommonResult.SUCCESS;
}

Mapper 입니다.

EmailAuthEntity selectEmailAuthByEmailCodeSalt(@Param(value = "email") String email,
                                               @Param(value = "code") String code,
                                               @Param(value = "salt") String salt);
                                               
 UserEntity selectUserByEmail(@Param(value = "email") String email);
 int updateUser(UserEntity user);

Mapper.xml입니다.

    <select id="selectEmailAuthByEmailCodeSalt"
            resultType="dev.test.study_member_bbs.entities.member.EmailAuthEntity">
        SELECT `index`        AS 'index',
               `email`        AS 'email',
               `code`         AS 'code',
               `salt`         AS 'salt',
               `created_on`   AS 'createdOn',
               `expires_on`   AS 'expiresOn',
               `expired_flag` AS 'isExpired'
        FROM `study_member`.`email_auths`
        WHERE BINARY `email` = #{email}
          AND BINARY `code` = #{code}
          AND BINARY `salt` = #{salt}
        LIMIT 1
    </select>

<select id="selectUserByEmail"
        resultType="dev.test.study_member_bbs.entities.member.UserEntity">
    SELECT `email`             AS `email`,
           `password`          AS `password`,
           `nickname`          AS `nickname`,
           `name`              AS `name`,
           `contact`           AS `contact`,
           `address_postal`    AS `addressPostal`,
           `address_primary`   AS `addressPrimary`,
           `address_secondary` AS `addressSecondary`,
           `registered_on`     As `registeredOn`
    FROM `study_member`.`user`
    WHERE BINARY `email` = #{email}
    LIMIT 1
</select>

    <update id="updateUser"
            parameterType="dev.test.study_member_bbs.entities.member.UserEntity">
        UPDATE `study_member`.`user`
        SET `password`          = #{password},
            `nickname`          = #{nickName},
            `name`              = #{name},
            `contact`           = #{contact},
            `address_postal`    = #{addressPostal},
            `address_primary`   = #{addressPrimary},
            `address_secondary` = #{addressSecondary},
            `registered_on`     = #{registeredOn}
        WHERE BINARY `email` = #{email}
        LIMIT 1
    </update>

updateUser에서 모든 값을 set하는 이유는 추후 nicnkName과 같이 다른 데이터를 수정할 때 mapper을 새롭게 만들어서 사용하는게 아닌 만들어 둔것을 사용하기 위합니다.(범용성)

Comments