티스토리 뷰
- DB 테이블 생성
CREATE SCHEMA `study_member`;
CREATE TABLE `study_member`.`users`
(
`email` VARCHAR(50) NOT NULL,
`password` VARCHAR(128) NOT NULL,
`nickname` VARCHAR(10) NOT NULL,
`name` VARCHAR(5) NOT NULL,
`contact` VARCHAR(12) NOT NULL,
`address_postal` VARCHAR(6) NOT NULL,
`address_primary` VARCHAR(100) NOT NULL,
`address_secondary` VARCHAR(100) NOT NULL,
`registered_on` DATETIME NOT NULL DEFAULT NOW(),
CONSTRAINT PRIMARY KEY (`email`),
CONSTRAINT UNIQUE (`nickname`),
CONSTRAINT UNIQUE (`contact`)
);
CREATE TABLE `study_member`.`email_auths`
(
`index` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`email` VARCHAR(50) NOT NULL,
`code` VARCHAR(6) NOT NULL,
`salt` VARCHAR(128) NOT NULL,
`created_on` DATETIME NOT NULL DEFAULT NOW(),
`expires_on` DATETIME NOT NULL,
`expired_flag` BOOLEAN NOT NULL DEFAULT FALSE,
CONSTRAINT PRIMARY KEY (`index`)
);
- UserEntity.java
package dev.shlee.studymemberbbs.entities.member;
import java.util.Date;
import java.util.Objects;
public class UserEntity {
private String email;
private String password;
private String nickname;
private String name;
private String contact;
private String address_postal;
private String address_primary;
private String address_secondary;
private String registered_on;
private Date registeredOn;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContact() {
return contact;
}
public void setContact(String contact) {
this.contact = contact;
}
public String getAddress_postal() {
return address_postal;
}
public void setAddress_postal(String address_postal) {
this.address_postal = address_postal;
}
public String getAddress_primary() {
return address_primary;
}
public void setAddress_primary(String address_primary) {
this.address_primary = address_primary;
}
public String getAddress_secondary() {
return address_secondary;
}
public void setAddress_secondary(String address_secondary) {
this.address_secondary = address_secondary;
}
public String getRegistered_on() {
return registered_on;
}
public void setRegistered_on(String registered_on) {
this.registered_on = registered_on;
}
public Date getRegisteredOn() {
return registeredOn;
}
public void setRegisteredOn(Date registeredOn) {
this.registeredOn = registeredOn;
}
@Override
public boolean equals(Object o) { //equals 재정의 기본키만 합니다
if (this == o) return true; // 스택값이 같으면 참
if (o == null || getClass() != o.getClass()) return false; //NULL 이거나 객체의 클래스랑 다르다면 false
UserEntity that = (UserEntity) o; //나랑은 다른데 같은 객체이다. 형변환
return Objects.equals(email, that.email); // 같은가의 여부...
}
@Override
public int hashCode() {
return Objects.hash(email);
}
}
- 게터세터 설정해주고 equals, hash는 기본키만 설정해준다.

- MemberMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="dev.shlee.studymemberbbs.mappers.IMemberMapper">
<select id="selectUserByEmail"
resultType="dev.shlee.studymemberbbs.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`.users
WHERE BINARY `email` = #{email}
LIMIT 1
</select>
</mapper>
- MemberService.java
1
@Service(value = "dev.shlee.studymemberbbs.services.MemberService")
public class MemberService {
private final IMemberMapper memberMapper;//변수로 만들때 I는 빼고 만드는게 국룰
@Autowired
public MemberService(IMemberMapper memberMapper) {
this.memberMapper = memberMapper;
}
@Transactional
public void sendEmailAuth(UserEntity user) { //UserEntity에게 이메일 검증을 요청하겠다
//1 0
//2 0
//3 x
//하나라도 안되면 위에거 전부취소
}
}
// 트랜잭션 적용하기
=============================================================================================
2
package dev.shlee.studymemberbbs.services;
import dev.shlee.studymemberbbs.entities.member.UserEntity;
import dev.shlee.studymemberbbs.enums.CommonResult;
import dev.shlee.studymemberbbs.enums.member.SendEmailAuthResult;
import dev.shlee.studymemberbbs.interfaces.IResult;
import dev.shlee.studymemberbbs.mappers.IMemberMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service(value = "dev.shlee.studymemberbbs.services.MemberService")
public class MemberService {
private final IMemberMapper memberMapper;//변수로 만들때 I는 빼고 만드는게 국룰
@Autowired
public MemberService(IMemberMapper memberMapper) {
this.memberMapper = memberMapper;
}
//1안
@Transactional
public Enum<? extends IResult> sendEmailAuth(UserEntity user) { //UserEntity에게 이메일 검증을 요청하겠다. 반드시 IResult를 구현하거나 상속받고 있어야한다.
return CommonResult.SUCCESS; //Enum은 name메서드를 가지고 있기 때문에 name메서드를 안만들어도 된다.
}
}
// 2안
// @Transactional
// public IResult sendEmailAuth(UserEntity user) { //UserEntity에게 이메일 검증을 요청하겠다. 반드시 U
// return CommonResult.SUCCESS; //interface에 name메서드를 넣어줘야함
//
// }
==========================================================================================================
//3
package dev.shlee.studymemberbbs.services;
import dev.shlee.studymemberbbs.entities.member.EmailAuthEntity;
import dev.shlee.studymemberbbs.entities.member.UserEntity;
import dev.shlee.studymemberbbs.enums.CommonResult;
import dev.shlee.studymemberbbs.enums.member.SendEmailAuthResult;
import dev.shlee.studymemberbbs.interfaces.IResult;
import dev.shlee.studymemberbbs.mappers.IMemberMapper;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
@Service(value = "dev.shlee.studymemberbbs.services.MemberService")
public class MemberService {
private final IMemberMapper memberMapper;//변수로 만들때 I는 빼고 만드는게 국룰
@Autowired
public MemberService(IMemberMapper memberMapper) {
this.memberMapper = memberMapper;
}
@Transactional
public Enum<? extends IResult> sendEmailAuth(UserEntity user, EmailAuthEntity emailAuth) throws NoSuchAlgorithmException { //UserEntity에게 이메일 검증을 요청하겠다. user은 controller에서 받아온다.
UserEntity existingUser = this.memberMapper.selectUserByEmail(user.getEmail());
if (existingUser != null) {
return SendEmailAuthResult.EMAIL_DUPLICATED; // null이 아니면 값이 있다는 것
}
String authCode = RandomStringUtils.randomNumeric(6); //6자의 랜덤한 문자열 가져오기
String authSalt = String.format("%s%s%f%f",
user.getEmail(),
authCode,
Math.random(),
Math.random());
StringBuilder authSaltHashBuilder = new StringBuilder();
MessageDigest md = MessageDigest.getInstance("SHA-512");
md.update(authSalt.getBytes(StandardCharsets.UTF_8));
for (byte hashByte : md.digest()) {
authSaltHashBuilder.append(String.format("%02x", hashByte));
}
authSalt = authSaltHashBuilder.toString();
Date createOn = new Date();
Date expiresOn = DateUtils.addMinutes(createOn, 5);
emailAuth.setCode(authCode);
emailAuth.setSalt(authSalt);
emailAuth.setCreatedOn(createOn);
emailAuth.setExpiresOn(expiresOn);
emailAuth.setExpired(false);
if (this.memberMapper.insertEmailAuth(emailAuth) == 0) {
return CommonResult.FAILURE;
}
return CommonResult.SUCCESS;
}
}
- MemberController
@RequestMapping(value = "/email",
method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE) //응답결과를 json으로 해석 조언
@ResponseBody // 문자열 그대로 나온다.
public String postEmail(UserEntity user, EmailAuthEntity emailAuth) throws NoSuchAlgorithmException { // 엔티티에서 가져온다.
Enum<?> result = this.memberService.sendEmailAuth(user, emailAuth);
return result.name().toLowerCase();
}
}

package dev.shlee.studymemberbbs.interfaces;
public interface IResult {
}
- IResult를 만들어주어야 열거형형태인 CommonResult랑 SendEmailAuthResult를 Service에서 상속받아서 두 개 만을 사용할 수 있다.
- CommonResult.java
package dev.shlee.studymemberbbs.enums;
import dev.shlee.studymemberbbs.interfaces.IResult;
public enum CommonResult implements IResult {
FAILURE, // 실패?
SUCCESS // 인증 번호를 전송하였습니다. 5분 이내에 입력해 주세요.
//name메서드를 구현하고 있어서 안 터짐.
}
- SendEmailAuthResult.java
package dev.shlee.studymemberbbs.enums.member;
import dev.shlee.studymemberbbs.interfaces.IResult;
public enum SendEmailAuthResult implements IResult { // member 메서드에 있는 SnedEmailAuth의 결과
EMAIL_DUPLICATED // 이미 사용중인 이메일 입니다.
}
- 의존성 추가
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
- MemberMapper.xml
<insert id="insertEmailAuth"
useGeneratedKeys="true"
keyColumn="index"
keyProperty="index"
parameterType="dev.shlee.study_web.entities.member.EmailAuthEntity">
INSERT INTO `study_member`.`email_auths` (`email`, `code`, `salt`, `created_on`, `expires_on`, `expired_flag`)
VALUES (#{email}, #{code}, #{salt}, #{createdOn}, #{expiresOn}, #{isExpired})
</insert>
insert 추가
- 결과

- 페이지에서 이메일을 입력하면 이렇게 나온다



진짜 너어어어ㅓ어ㅓ어어어ㅓ어어어ㅓㅇ어무 어렵다!
'웹 개발 > SpringBoot' 카테고리의 다른 글
| [Spring Boot] MVC 패턴 (2) | 2022.11.03 |
|---|---|
| [Spring Boot] 이메일 인증 구현 과정 (3) | 2022.11.03 |
| [Spring Boot] Test 인증번호 6자리 (3) | 2022.11.02 |
| [Spring Boot] interface, XML, Service (2) | 2022.11.02 |
| [Spring Boot] HTML, CSS, JS 및 AJAX 기능구현 (1) | 2022.11.02 |
댓글