Been_DevStep
SpringBoot 이메일 인증(1) 본문
1 받은 이메일을 사용하는 유저가 레코드가 잇는가? -> 이미 사용중인 이메일이 주소입니다.
2 (Apache Commons Langs 사용하여)인증번호 및 솔트(Salt)생성 후 테이블에 인서트
3 <2>에서 생성된 인증번호 전송 -> " 인증번호를 전송하였습니다. 5분이내에 입력해 주세요."
이 모든 동작은 transaction(트랜잭션)이 적용되어야한다.
Controller
//이메일 인증 요청을 위한 인증번호를 전송하기위한 Controller
@RequestMapping(value = "email", method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE) //value 는 js와 연결
@ResponseBody//String 결과값이 타임리프 문이 아니라 그냥 결과값이 출력됨
public String postEmail(UserEntity user, EmailAuthEntity emailAuth) throws MessagingException {
Enum<?> result = this.memberService.sendEmailAuth(user, emailAuth);
JSONObject responseObject = new JSONObject();
responseObject.put("result", result.name().toLowerCase());
if (result == CommonResult.SUCCESS)
responseObject.put("salt", emailAuth.getSalt());
//실패라면 굳이 데이터를 추가로 보낼 필요가 없기때문에 성공일 경우 데이터를 담아보냅니다.
//Salt는 추후 회원가입할때 확인하기 위해서 데이터를 담아서 보내줍니다.
//이 값은 hidden 으로 보관할 것 입니다.
return responseObject.toString();
//toLowerCase를 사용하는 이유는 JAVA로 개발했다는 것을 숨기기 위해서
}
Service
@Transactional // 트랜잭션 설정.
public Enum< ? extends IResult> sendEmailAuth(UserEntity user, EmailAuthEntity emailAuth) {
UserEntity existingUser = this.memberMapper.selectUserByEmail(user.getEmail());
// null 이 아니라면 이미 동일한 email 로 가입이 되어있다는 의미이기
// 때문에 중복 결과를 return 합니다.
if(existingUser != null) return CommonResult.FAILURE;
Service에서 결과값을 Enum을 반환해줍니다.
SendEmailAuthResult
//서비스이름.결과값
public enum SendEmailAuthResult implements IResult {
EMAIL_DUPLICATED
}
IMemberMapper Interface
UserEntity selectUserByEmail(@Param(value = "email") String email);
MemberMapper.xml
<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>
Service에서 결과 값이 null이 아니라고 판명 되었다는 것은 중복체크가 끝났다는 의미입니다.
중복 체크가 끝났다면 emailAuth에 담을 데이터를 만들어주고 email_auth table에 담아줍니다.
//emailAuth 에 담을 email set
emailAuth.setEmail(user.getEmail());
//random code 6자리 set
//RandomStringUtils.randomNumeric(count) 는
//count 만큼의 숫자를 랜덤으로 생성한뒤 문자열로 반환해준다.
String code = RandomStringUtils.randomNumeric(6);
emailAuth.setCode(code);
// 랜덤한 salt 생성을 Math.random 을 사용한다.
// Math.random 는 0... ~ 0.9...까지의 값을 반환 한다.
String salt = String.format("%s%s%s%s", user.getEmail(), code, Math.random(), Math.random());
//생선한 salt 는 hashing 해서 set
emailAuth.setSalt(CryptoUtils.hashSha512(salt));
// slat 생성 시간.
Date createdOn = new Date();
emailAuth.setCreatedOn(createdOn);
// slat 생성 시간에서 5분을 더한 만료시간.
emailAuth.setExpiresOn(DateUtils.addMinutes(createdOn, 5));
//아직 인증을 완료하지 않았기 때문에 기본값인 false set
emailAuth.setExpired(false);
// 만들어준 emailAuth 를 db에 담아줍니다.
// insertEmailAuth 의 return 값은 int 인데 이 때 int 는
// insertEmailAuth 작업을 통해 영향을 끼친 레코드의 갯수를 의미합니다.
// 값이 0 이라면 insert 가 안되었다는 의미 이기 때문에 FAILURE
if (memberMapper.insertEmailAuth(emailAuth) == 0)
return CommonResult.FAILURE;
return CommonResult.SUCCESS;
}
IMemberMapper Interface
int insertEmailAuth(EmailAuthEntity emailAuth);
MemberMapper.xml
<insert id="insertEmailAuth"
useGeneratedKeys="true"
keyProperty="index"
keyColumn="index"
parameterType="dev.test.study_member_bbs.entities.member.UserEntity">
INSERT INTO `study_member`.`email_auths` (`email`, `code`, `salt`, `created_on`, `expires_on`, `expired_flag`)
VALUES (#{email}, #{code}, #{salt}, #{createdOn}, #{expiresOn}, #{isExpired})
</insert>
Table에 PK가 index일 경우 useGeneratedKeys, keyProperty, keyColumn을 걸어줍니다.
register.js
const xhr = new XMLHttpRequest();
const formData = new FormData();
formData.append('email', form['email'].value);
// (1.해당 Controller의 ReuestParam or
//매개변수에 있는 멤버변수의 이름과 동일하게사용.
// 2.전송하고자하는 데이터가 속해있는 태그의 name )
xhr.open('POST', './email');
xhr.onreadystatechange = () => {
if (xhr.readyState == XMLHttpRequest.DONE) {
Cover.hide();
if (xhr.status >= 200 && xhr.status < 300) {
//status 가 200~ 299 까지는 성공 300~500 모종의 이유로 실패
//http error code 참고
console.log(xhr.responseText);
} else {
form.querySelector('[rel="emailWarning"]').innerText = '서버와 통신하지 못하였습니다. 잠시후 다시 시도해주세요.';
form.querySelector('[rel="emailWarning"]').classList.add('visible');
}
}
};
xhr.send(formData);
를통해서
해당 이미지에 Response의 'success' 는 Controller의 retrun 값이고
Console은 js의 출력물 입니다.
'공부 > SpringBoot' 카테고리의 다른 글
Spring Boot 이메일 인증(3) - 인증 확인 (0) | 2022.11.08 |
---|---|
Spring Boot 이메일 인증(2) - 실제 메일 보내기 (0) | 2022.11.07 |
SpringBoot 우편번호 검색/주소 찾기 (0) | 2022.11.01 |
SpringBoot 빈칸일 경우 경고메세지 (0) | 2022.10.30 |
SpringBoot MemoController - page (0) | 2022.10.30 |
Comments