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 이메일 인증(3) - 인증 확인 본문

공부/SpringBoot

Spring Boot 이메일 인증(3) - 인증 확인

JChBeen 2022. 11. 8. 12:28

인증번호를 전송했다면 인증번호를 입력하고 인증번호 확인 버튼을 눌렀을 경우의 진행입니다.

 

Controller에서는 PATCH를 통해서 인증번호를 확인합니다.

//인증 번호를 확인하기위한 Controller
@RequestMapping(value = "email", method = RequestMethod.PATCH,
        produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public String patchEmail(EmailAuthEntity emailAuth) {
    Enum<?> result = this.memberService.verifyEmailAuth(emailAuth);
    JSONObject responseObject = new JSONObject();
    responseObject.put("result", result.name().toLowerCase());

    return responseObject.toString();
}

Service에 인증코들 전송하기 위해 입력했던 이메일과 이메일 전송을 성공한뒤 html에서 hidden으로 받아둔 code, salt를 받아와서 email_auth에 값이 있는지 확인합니다.

    @Transactional
    public Enum<? extends IResult> verifyEmailAuth(EmailAuthEntity emailAuth){
        EmailAuthEntity existingEmailAuth = memberMapper.selectEmailAuthByEmailCodeSalt(
                emailAuth.getEmail(), emailAuth.getCode(), emailAuth.getSalt()
        );

email, code(인증번호), salt 를 통해서 값을 가져옵니다.

IMemberMapper Interface

EmailAuthEntity selectEmailAuthByEmailCodeSalt(@Param(value = "email") String email,
                                               @Param(value = "code") String code,
                                               @Param(value = "salt") String salt);

 

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>

 

가져온 값을 담은 existingEmailAuth가 null이이면 FAILURE를 반환, 입력시간이 5분을 초과했다면  VerifyEmailAuthResult enum을 만들어서 EXPIRED을 반환하여 추후 js 에서 5분을 초과했을때의 처리를 합니다.

// null 값이면 검색 결과가 없다는것
if(existingEmailAuth == null) return CommonResult.FAILURE;

// 인증번호 입력시간 초과
if(existingEmailAuth.getExpiresOn().compareTo(new Date()) < 0)
    return VerifyEmailAuthResult.EXPIRED;

null이 아니고 입력시간 이내에 인증번호를 입력했다면 인증을 성공했다는 값을 가진 expired 값을true로 set하고 지금 비교하고 있는 레코드의 값을 update 해줍니다.

existingEmailAuth.setExpired(true);

// 0이면 update 가 제대로 안되었다는 의미.
if(this.memberMapper.updateEmailAuth(existingEmailAuth) == 0)
    return CommonResult.FAILURE;

return CommonResult.SUCCESS;

이때 updateEmailAuth의 반환값이 0이라면 제대로 update가 안됬다는 의미이기 때문에 FAILURE를 반환합니다.

 

Mapper Interface

int updateEmailAuth(EmailAuthEntity emailAuth);

Mappber.xml

<update id="updateEmailAuth"
        parameterType="dev.test.take_a_walk_duo.entities.member.EmailAuthEntity">
    UPDATE `take_a_walk_duo_member`.`email_auths`
    SET `email`        = #{email},
        `code`         = #{code},
        `salt`         = #{salt},
        `created_on`   = #{createdOn},
        `expires_on`   = #{expiresOn},
        `expired_flag` = #{isExpired}
    WHERE BINARY `index` = #{index}
    LIMIT 1
</update>

 

이메일을 통해서 받은 인증번호를 입력하고 인증번호를 확인버튼을 누를때 js입니다.

form['emailVerify'].addEventListener('click', () => {
    if (form['emailAuthCode'].value === '') {
        EmailWarning.show('인증 번호를 입력해주세요.');
        form['emailAuthCode'].focus();
        return;
    }
    if (!new RegExp('^(\\d{6})$').test(form['emailAuthCode'].value)) {
        EmailWarning.show('올바른 인증 번호를 입력해 주세요');
        form['emailAuthCode'].focus();
        form['emailAuthCode'].select();
        return;
    }
    Cover.show('인증 번호를 확인하고 있습니다. \n\n 잠시만 기다려주세요.');
    const xhr = new XMLHttpRequest();
    const formData = new FormData;
    formData.append('email', form['email'].value);
    formData.append('code', form['emailAuthCode'].value);
    formData.append('salt', form['emailAuthSalt'].value);

    xhr.open('PATCH', './email');
    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 'expired' :
                        EmailWarning.show("인증 정보가 만료되었습니다. 다시 시도해 주세요.");
                        form['email'].removeAttribute('disabled');
                        form['email'].focus();
                        form['email'].select();
                        //실패했기 때문에 다시 입력하기 위해서 커서의 위치를 옮겨줍니다.
                        form['emailSend'].removeAttribute('disabled');
                        form['emailAuthCode'].value = '';
                        form['emailAuthCode'].setAttribute('disabled', 'disabled');
                        form['emailAuthSalt'].value = '';
                        form['emailVerify'].setAttribute('disabled', 'disabled');
                        break;
                    case `success`:
                        EmailWarning.show('이메일이 정상적으로 인증되었습니다.');
                        form['emailAuthCode'].setAttribute('disabled', 'disabled');
                        form['emailVerify'].setAttribute('disabled', 'disabled');
                        form['password'].focus();
                        //인증되었기 때문에 더이상 사용자가 수정하는것을 방지하기 위해서
                        //비활성화 해줍니다.
                        break;
                    default:
                        EmailWarning.show('');
                        form['emailAuthCode'].focus();
                }

            } else {
                EmailWarning.show('서버와 통신하지 못하였습니다. 잠시 후 다시 시도해 주세요.');
            }
        }
    };
    xhr.send(formData);

});
Comments