09009
[Spring] 예제 2 - 암호화, 메일인증 본문
암호화 담당 클래스 생성
암호화 관련 메서드는 static으로 설계할 것이다.
package com.ja.finalproject.util;
import java.security.MessageDigest;
public class PasswordEncoder {
public static String encoding(String value) {
System.out.println("해싱 전 비밀번호 : " + value);
String hashCode = null;
//password hashing...
try {
// sha-1 방식으로 messageDigest 실행 (sha-1은 이제 잘 쓰지 않는다.)
MessageDigest messageDigest = MessageDigest.getInstance("sha-1");
messageDigest.reset();
messageDigest.update(value.getBytes("UTF-8")); //해싱할 값 세팅..
byte [] chars = messageDigest.digest(); //해싱 값... 도출...
StringBuilder sb = new StringBuilder();
for(int i = 0 ; i < chars.length ; i++) {
String tmp = Integer.toHexString(chars[i] & 0xff);
if(tmp.length() == 1) {
sb.append("0");
}
sb.append(tmp);
}
hashCode = sb.toString();
}catch(Exception e) {
e.printStackTrace();
}
System.out.println("해싱 후 비밀번호 : " + hashCode);
return hashCode;
}
}
✍ MemberServiceImpl
입력한 비밀번호가 insert되기 전에 암호화 작업이 처리되고 암호화 처리된 비밀번호를 DTO에 넣고
insert 한다.
// insert 하기 전에 비밀번호 암호화
String pw = memberDto.getUser_pw(); // pw = 입력된 패스워드
pw = PasswordEncoder.encoding(pw);
memberDto.setUser_pw(pw);
memberSqlMapper.insert(memberDto);
public void register(MemberDto memberDto, int[] hobby_id) {
System.out.println("여기서 알고리즘 수행");
int memberPk = memberSqlMapper.createPk(); // primary key 생성, nextval이 실행된다.
// ! 중요 !
memberDto.setId(memberPk); // 파라미터로 안받기 때문에 SET으로 해주어야함.
// insert 하기 전에 비밀번호 암호화
String pw = memberDto.getUser_pw(); // pw = 입력된 패스워드
pw = PasswordEncoder.encoding(pw);
memberDto.setUser_pw(pw);
memberSqlMapper.insert(memberDto);
if(hobby_id != null) {
for(int hobbyId : hobby_id) {
MemberHobbyDto memberHobbyDto = new MemberHobbyDto();
memberHobbyDto.setHobby_id(hobbyId);
memberHobbyDto.setMember_id(memberPk);
memberSqlMapper.insertMemberHobby(memberHobbyDto);
}
}
}
회원가입 시 비밀번호를 1111로 입력하고 데이터베이스를 확인하면
암호화 처리된 비밀번호가 나온다.
로그인 시 인코딩 처리도 해주어야 한다.
// controller 쪽에서 있는지 없는지 판단해야하므로 리턴타입을 만든다.
public MemberDto getMemberByIdAndPw(MemberDto memberDto) {
String pw = memberDto.getUser_pw(); // pw = 입력된 패스워드
pw = PasswordEncoder.encoding(pw);
memberDto.setUser_pw(pw);
MemberDto sessionUser = memberSqlMapper.selectByUserIdAndPw(memberDto);
// 데이터베이스에 select된 결과로서의 dto -> sessionUser
return sessionUser;
}
메일 인증
pom.xml에 메일 관련 라이브러리 추가
<!-- Mail 관련 라이브러리 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>
root-context.xml에 설정
username, password는 변경해야함.
password: 구글 웹 비밀번호
<!-- 메일 전송 관련 라이브러리 세팅... -->
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="smtp.gmail.com" />
<property name="port" value="587" />
<property name="username" value=" @ .com" />
<property name="password" value=" " />
<!-- email 요청시는 SMTP -->
<property name="javaMailProperties">
<props>
<prop key="mail.transport.protocol">smtp</prop>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.starttls.enable">true</prop>
<prop key="mail.debug">false</prop>
<prop key="mail.smtp.ssl.trust">smtp.gmail.com</prop>
<prop key="mail.smtp.ssl.protocols">TLSv1.2</prop>
</props>
</property>
</bean>
MemberServiceImpl
논리적으로 해결이 안되는 문제는 try -catch 문을 사용하는 편이다.
public void register(MemberDto memberDto, int[] hobby_id) {
System.out.println("여기서 알고리즘 수행");
int memberPk = memberSqlMapper.createPk(); // primary key 생성, nextval이 실행된다.
// ! 중요 !
memberDto.setId(memberPk); // 파라미터로 안받기 때문에 SET으로 해주어야함.
// insert 하기 전에 비밀번호 암호화
String pw = memberDto.getUser_pw(); // pw = 입력된 패스워드
pw = PasswordEncoder.encoding(pw);
memberDto.setUser_pw(pw);
memberSqlMapper.insert(memberDto);
if(hobby_id != null) {
for(int hobbyId : hobby_id) {
MemberHobbyDto memberHobbyDto = new MemberHobbyDto();
memberHobbyDto.setHobby_id(hobbyId);
memberHobbyDto.setMember_id(memberPk);
memberSqlMapper.insertMemberHobby(memberHobbyDto);
}
}
// 이메일 보내기
try {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
// subject: 제목
mimeMessageHelper .setSubject("제목 테스트!!!!!");
mimeMessageHelper.setText("본문 테스트!!!!");
mimeMessageHelper.setFrom("admin", "관리자");
//누구한테 보낼 것인가? (받는 쪽)
mimeMessageHelper.setTo("kindred09009@gmail.com");
javaMailSender.send(mimeMessage);
} catch (Exception e) {
e.printStackTrace();
}
}
회원가입 수행하면 메일이 수신되었다.
메일 인증 테이블 설계
한 명의 회원이 이메일 인증을 여러 번 할 수 있다.
일대 다 관계
처음에는 인증완료시간이 없으므로 NULL값 허용해야함
public void register(MemberDto memberDto, int[] hobby_id) {
System.out.println("여기서 알고리즘 수행");
int memberPk = memberSqlMapper.createPk(); // primary key 생성, nextval이 실행된다.
// ! 중요 !
memberDto.setId(memberPk); // 파라미터로 안받기 때문에 SET으로 해주어야함.
// insert 하기 전에 비밀번호 암호화
String pw = memberDto.getUser_pw(); // pw = 입력된 패스워드
pw = PasswordEncoder.encoding(pw);
memberDto.setUser_pw(pw);
memberSqlMapper.insert(memberDto);
if(hobby_id != null) {
for(int hobbyId : hobby_id) {
MemberHobbyDto memberHobbyDto = new MemberHobbyDto();
memberHobbyDto.setHobby_id(hobbyId);
memberHobbyDto.setMember_id(memberPk);
memberSqlMapper.insertMemberHobby(memberHobbyDto);
}
}
// 이메일 보내기
try {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
// subject: 제목
mimeMessageHelper .setSubject("FP 회원가입을 축하드립니다.");
String mailAuthKey = UUID.randomUUID().toString();
String text = mailAuthKey;
mimeMessageHelper.setText(text);
mimeMessageHelper.setFrom("admin", "관리자");
//누구한테 보낼 것인가? (받는 쪽)
mimeMessageHelper.setTo(memberDto.getEmail()); // 회원가입 시 작성한 이메일
javaMailSender.send(mimeMessage);
} catch (Exception e) {
e.printStackTrace();
}
}
테이블 생성
DATE TABLE fp_mail_auth;
-- 이메일 인증 T
CREATE TABLE fp_mail_auth(
id NUMBER PRIMARY KEY,
member_id NUMBER,
key VARCHAR2(200),
complete VARCHAR2(1),
complete_date DATE
);
DROP SEQUENCE fp_mail_auth_seq;
CREATE SEQUENCE fp_mail_auth_seq;
DTO 생성
MailAuthDto
package com.ja.finalproject.dto;
import java.util.Date;
public class MailAuthDto {
private int id;
private int member_id;
private String key;
private String complete;
private Date complete_date;
public MailAuthDto() {
super();
}
public MailAuthDto(int id, int member_id, String key, String complete, Date complete_date) {
super();
this.id = id;
this.member_id = member_id;
this.key = key;
this.complete = complete;
this.complete_date = complete_date;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getMember_id() {
return member_id;
}
public void setMember_id(int member_id) {
this.member_id = member_id;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getComplete() {
return complete;
}
public void setComplete(String complete) {
this.complete = complete;
}
public Date getComplete_date() {
return complete_date;
}
public void setComplete_date(Date complete_date) {
this.complete_date = complete_date;
}
}
이제 회원가입할 때 3개의 테이블에 동시에 insert 될 것이다.
MemberSqlMapper
// 메일 인증
public void insertMailAuth(MailAuthDto mailAuthDto);
public void updateCompleteYByKey(String key);
MemberSqlMapper.xml
<insert id="insertMailAuth">
INSERT INTO fp_mail_auth VALUES(
fp_mail_auth_seq.nextval,
#{member_id},
#{key},
'N',
null
)
</insert>
<update id="updateCompleteYByKey">
UPDATE fp_mail_auth
SET
complete = 'Y',
complete_date = SYSDATE
WHERE key = #{key}
</update>
MemberServiceImpl
String mailAuthKey = UUID.randomUUID().toString();
MailAuthDto mailAuthDto = new MailAuthDto();
mailAuthDto.setMember_id(memberPk);
mailAuthDto.setKey(mailAuthKey);
memberSqlMapper.insertMailAuth(mailAuthDto);
코드 수정
public void register(MemberDto memberDto, int[] hobby_id) {
System.out.println("여기서 알고리즘 수행");
int memberPk = memberSqlMapper.createPk(); // primary key 생성, nextval이 실행된다.
// ! 중요 !
memberDto.setId(memberPk); // 파라미터로 안받기 때문에 SET으로 해주어야함.
// insert 하기 전에 비밀번호 암호화
String pw = memberDto.getUser_pw(); // pw = 입력된 패스워드
pw = PasswordEncoder.encoding(pw);
memberDto.setUser_pw(pw);
memberSqlMapper.insert(memberDto);
if(hobby_id != null) {
for(int hobbyId : hobby_id) {
MemberHobbyDto memberHobbyDto = new MemberHobbyDto();
memberHobbyDto.setHobby_id(hobbyId);
memberHobbyDto.setMember_id(memberPk);
memberSqlMapper.insertMemberHobby(memberHobbyDto);
}
}
String mailAuthKey = UUID.randomUUID().toString();
MailAuthDto mailAuthDto = new MailAuthDto();
mailAuthDto.setMember_id(memberPk);
mailAuthDto.setKey(mailAuthKey);
memberSqlMapper.insertMailAuth(mailAuthDto);
// 이메일 보내기
try {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
// subject: 제목
mimeMessageHelper .setSubject("FP 회원가입을 축하드립니다.");
String text = "";
text += "회원가입을 축하드립니다. <br>";
text += "아래 링크를 클릭하셔서 인증을 완료하신 후 이용 가능합니다. <br>";
text += "<a href='http://localhost:8181/finalproject/member/successMail?key="+mailAuthKey+"'>인증하기</a>";
mimeMessageHelper.setText(text, true); // html로 날라간다.
mimeMessageHelper.setFrom("admin", "관리자");
//누구한테 보낼 것인가? (받는 쪽)
mimeMessageHelper.setTo(memberDto.getEmail()); // 회원가입 시 작성한 이메일
javaMailSender.send(mimeMessage);
} catch (Exception e) {
e.printStackTrace();
}
}
메서드 추가
public void successMail(String key) {
memberSqlMapper.updateCompleteYByKey(key);
}
MemberController
@RequestMapping("successMail")
public String successMail(String key) {
memberService.successMail(key);
return "member/completeMailAuth";
}
completeMailAuth.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
이메일 인증이 완료되었습니다. 로그인 후 이용 가능합니다. <br>
<a href="../board/mainPage">메인 페이지</a>
<a href="../member/loginPage">로그인</a>
</body>
</html>
로그인 쿼리 변경
memberSqlMapper.xml
<!-- select는 꼭 result 타입을 세팅해주어야 한다. -->
<select id="selectByUserIdAndPw" resultType="com.ja.finalproject.dto.MemberDto">
SELECT fm.*
FROM fp_member fm INNER JOIN fp_mail_auth fma ON fm.id = fma.member_id
WHERE fm.user_id = #{user_id}
AND fm.user_pw = #{user_pw}
AND fma.complete = 'Y'
</select>
loginFail.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
로그인 실패, 아이디 혹은 비밀번호를 확인해주세요. 혹은 이메일 인증을 해야합니다. <br>
<a href="./loginPage">로그인 페이지로 이동</a>
</body>
</html>
회원가입 때 소요되는 시간이 길어지는 문제
- 병렬처리 : 쓰레드
쓰레드 클래스 생성
MemberServiceImpl
package com.ja.finalproject.member.service;
import java.util.List;
import java.util.UUID;
import javax.mail.internet.MimeMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import com.ja.finalproject.dto.HobbyCategoryDto;
import com.ja.finalproject.dto.MailAuthDto;
import com.ja.finalproject.dto.MemberDto;
import com.ja.finalproject.dto.MemberHobbyDto;
import com.ja.finalproject.member.mapper.MemberSqlMapper;
import com.ja.finalproject.util.PasswordEncoder;
@Service
public class MemberServiceImpl {
@Autowired
private MemberSqlMapper memberSqlMapper;
@Autowired
private JavaMailSender javaMailSender;
public void register(MemberDto memberDto, int[] hobby_id) {
System.out.println("여기서 알고리즘 수행");
int memberPk = memberSqlMapper.createPk(); // primary key 생성, nextval이 실행된다.
// ! 중요 !
memberDto.setId(memberPk); // 파라미터로 안받기 때문에 SET으로 해주어야함.
// insert 하기 전에 비밀번호 암호화
String pw = memberDto.getUser_pw(); // pw = 입력된 패스워드
pw = PasswordEncoder.encoding(pw);
memberDto.setUser_pw(pw);
memberSqlMapper.insert(memberDto);
if(hobby_id != null) {
for(int hobbyId : hobby_id) {
MemberHobbyDto memberHobbyDto = new MemberHobbyDto();
memberHobbyDto.setHobby_id(hobbyId);
memberHobbyDto.setMember_id(memberPk);
memberSqlMapper.insertMemberHobby(memberHobbyDto);
}
}
String mailAuthKey = UUID.randomUUID().toString();
MailAuthDto mailAuthDto = new MailAuthDto();
mailAuthDto.setMember_id(memberPk);
mailAuthDto.setKey(mailAuthKey);
memberSqlMapper.insertMailAuth(mailAuthDto);
// // 이메일 보내기 (쓰레드 처리)
new MailSendThread(javaMailSender, memberDto.getEmail(), mailAuthKey).start();
}
// controller 쪽에서 있는지 없는지 판단해야하므로 리턴타입을 만든다.
public MemberDto getMemberByIdAndPw(MemberDto memberDto) {
String pw = memberDto.getUser_pw(); // pw = 입력된 패스워드
pw = PasswordEncoder.encoding(pw);
memberDto.setUser_pw(pw);
MemberDto sessionUser = memberSqlMapper.selectByUserIdAndPw(memberDto);
// 데이터베이스에 select된 결과로서의 dto -> sessionUser
return sessionUser;
}
public List<HobbyCategoryDto> getHobbyList() {
return memberSqlMapper.selectHobbyList();
}
public void successMail(String key) {
memberSqlMapper.updateCompleteYByKey(key);
}
}
class MailSendThread extends Thread {
private JavaMailSender javaMailSender;
private String to;
private String key;
public MailSendThread(JavaMailSender javaMailSender, String to, String key) {
super();
this.javaMailSender = javaMailSender;
this.to = to;
this.key = key;
}
public void run() {
try {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
// subject: 제목
mimeMessageHelper .setSubject("FP 회원가입을 축하드립니다.");
String text = "";
text += "회원가입을 축하드립니다. <br>";
text += "아래 링크를 클릭하셔서 인증을 완료하신 후 이용 가능합니다. <br>";
text += "<a href='http://localhost:8181/finalproject/member/successMail?key="+key+"'>인증하기</a>";
mimeMessageHelper.setText(text, true); // html로 날라간다.
mimeMessageHelper.setFrom("admin", "관리자");
//누구한테 보낼 것인가? (받는 쪽)
mimeMessageHelper.setTo(to); // 회원가입 시 작성한 이메일
javaMailSender.send(mimeMessage);
} catch (Exception e) {
e.printStackTrace();
}
}
}
registerComplete.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
회원가입이 완료되었습니다. 메일인증 후 로그인 가능합니다. 메일을 확인하여 주시기 바랍니다.
메일 전송은 3분정도 소요될 수 있습니다. <a href="./loginPage">로그인 페이지로</a>
</body>
</html>
'Back-End > Spring' 카테고리의 다른 글
[Spring] 예제 2 - resources 경로 이미지 (0) | 2023.05.24 |
---|---|
[Spring] 예제 2 - Interceptor (0) | 2023.05.24 |
[Spring] 예제 1 연습 - 테이블 설계 (0) | 2023.05.23 |
[Spring] 예제 2 - 파일 업로드 (0) | 2023.05.23 |
[Spring] 예제 2 - 검색 기능 구현 (0) | 2023.05.23 |