1. 기능설명
클라이언트가 작성한 이메일로 '랜덤 6자리' 인증번호를 전송하여 입력한 인증번호가 동일한지 검증하기
[ 상세 설명 ]
(사전 설정) MailConfig.java ▶ 메일 보낼 방식인 Gmail(Smtp방식), 보낼 사람의 이메일과 비밀번호, 프로토콜 등 환경 설정하기
(사전 설정) MailService.java ▶ Smtp 방식인 Gmail을 Mime형식으로 전달될 수 있도록 메소드 작성하기
(인증번호전송 기능)
이메일 입력 후 '인증번호전송' 버튼 클릭하면 자바스크립트 'sendAuth()' 메소드 작동
자바스크립트 sendAuth() 메소드에서는 Controller에 post방식으로 자바 'sendAuth()' 메소드에 클라이언트가 입력한 이메일 전달
자바 sendAuth() 메소드에서는 이메일 검증과 '랜덤 6자리' 인증번호 생성하여 Session에 저장 및 받은 이메일로 인증번호 발송
(인증번호확인 기능)
클라이언트가 동일한 인증번호 입력 후 '인증번호 확인' 버튼 클릭하면 자바스크립트 'checkAuth()'메소드 작동
자바스크립트 checkAuth() 메소드에서는 Controller에 post방식으로 자바 'checkAuth()' 메소드에 클라이언트가 입력한 인증번호 전달
자바 checkAuth() 메소드에서는 생성된 Session의 인증번호의 값과 동일한지 검증
자바스크립트 'sendAuth()'와 'checkAuth()' 메소드 둘다
클라이언트 화면 변화가 있을 경우 controller에서 응답값을 받는 자바스크립트 'emailMsg()' 메소드 작동
emailMsg() 메소드에서는 받은 응답값을 화면에 출력한다.
2. 추가한 라이브러리
Library | |
Spring Context Support | JavaMailSender, JavaMailSenderImpl, MimeMessageHelper 객체를 사용하기 위함. |
JavaMail API | 메일 발송을 위한 라이브러리 |
3. 코드
[ 사전 설정 ]
(MailConfig.java)
package com.care.db.basic.config;
import java.util.Properties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
@Configuration
public class MailConfig {
@Bean
public JavaMailSender mailSender() {
JavaMailSenderImpl jms = new JavaMailSenderImpl();
jms.setHost("smtp.gmail.com"); // gmail이 smtp방식을 사용한다.
jms.setPort(587); // gmail TSL 포트번호
jms.setUsername("보낼이메일입력@gmail.com"); // 인증번호를 클라이언트에게 보낼 이메일 주소.
jms.setPassword("임시비밀번호 입력"); // 비밀번호, 예제로는 구글 임시 앱 비밀번호를 사용 : 구글 계정 관리 > 보안 > 앱 비밀번호(2차 인증해야 사용가능)
Properties pro = new Properties();
pro.setProperty("mail.transport.protocol", "smtp"); // 프로토콜 : 데이터 양식
pro.setProperty("mail.smtp.auth", "true"); // smtp 검증할 것인지 true설정
pro.setProperty("mail.smtp.starttls.enable", "true"); // 암호화 통신
jms.setJavaMailProperties(pro);
return jms;
}
}
JavaMailSender 객체에는 보낼 사람의 이메일방식과 프로토콜 방식을 설정해주는 인스턴스를 만들어야 한다.
예시에서는 gmail 이메일을 이용해 인증번호를 발송하려고 한다.
JavaMailSenderImpl 객체 변수를 생성하여 이용하여 이메일 방식들을 넣어주어 반환해주는 JavaMailSender 인스턴스를 만들어주자.
gmail은 SMTP 방식으로 메일을 발송하고 포트번호는 587로 설정되어 있다.
(*SSL을 사용하는 경우 465, TLS를 사용하는 경우 587 이다. SSL과 TLS가 무엇인가요?)
보낼 사람의 gmail 이메일과 비밀번호를 설정해주어야 인증번호 발송 이메일이 설저이 되는데,
해당 비밀번호는 사용자의 진짜 비밀번호가 아닌 임시 비밀번호를 넣어주기로 한다.(코드상에 노출될 것을 주의)
임시 비밀번호는 보낼 이메일 계정을 구글에서 로그인하여 [ 계정관리 ] > [ 보안 ] > [ 2차 인증 ] > [ 앱 비밀번호 생성 ] 을 하면 만들 수 있다.
생성된 구글 임시 비밀번호값을 넣어준다.
그 외 데이터 전송 양식들은 프로퍼티 형태로 JavaMailSenderImpl 객체에 넣어주면된다.
(MaileService.jsp)
package com.care.db.basic.service;
import javax.mail.MessagingException;
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;
@Service
public class MailService {
// MailConfig에 JavaMailSender 객체 생성이 성공해야 사용 가능.
@Autowired private JavaMailSender mailSender;
public void sendMail(String to, String subject, String content) {
// Mime(MIME) : 전자 우현 포멧 형식(SMTP를 MIME형식으로 전달됨)
MimeMessage message = mailSender.createMimeMessage();
try {
MimeMessageHelper messageHelper = new MimeMessageHelper(message, true, "UTF-8");
messageHelper.setSubject(subject); // 이메일의 제목
messageHelper.setText(content);// 이메일의 본문
messageHelper.setTo(to); // 수신자
mailSender.send(message);
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
객체 생성한 JavaMailSender를 @Autowired하여 이메일 제목, 내용, 수신자를 입력해서 메일을 보내는 서비스 메소드를 만들자.
[ 클라이언트 화면 ]
(member.jsp 의 html 코드)
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<body>
<font id="emailMsg" color="red"></font>
<form action="member" method="post">
<input type="text" name="id" id="id" placeholder="아이디">
<input type="button" value="중복 확인" onclick="doubleCheck()"><br>
<input type="password" name="pw" placeholder="비밀번호"><br>
<input type="password" name="confirmPw" placeholder="비밀번호 확인"><br>
<input type="text" name="name" placeholder="이름"><br>
<input type="text" name="email" id="email" placeholder="이메일">
<input type="button" value="인증 번호 전송" onclick="sendAuth()"><br>
<input type="text" name="authNumber" id="authNumber" placeholder="인증 번호">
<input type="button" value="인증 번호 확인" onclick="checkAuth()"><br><br>
<input type="submit" value="회원 가입">
<input type="button" value="취소" onclick="location.href='index'">
</form>
</body>
</html>
(member.jsp 의 javaScript 코드)
<script>
// 메일 인증 기능
var req;
function sendAuth() {
req = new XMLHttpRequest();
req.onreadystatechange = emailMsg
var email = document.getElementById('email').value
req.open('post', 'sendAuth')
req.send(email)
}
function checkAuth() {
req = new XMLHttpRequest();
req.onreadystatechange = emailMsg
var authNumber = document.getElementById('authNumber').value
req.open('post', 'checkAuth')
req.send(authNumber)
}
function emailMsg() {
if (req.readyState == 4 && req.status == 200) {
var emailMsg = document.getElementById('emailMsg')
emailMsg.innerHTML = req.responseText
}
}
</script>
emailMsg() 메소드의 if문의 'readyState == 4'는 해당 페이지의 출력이 다 완료되었을때를 가르키며, 'status == 200'은 해당페이지의 http 응답 코드로 200은 정상적으로 서버가 작동되었을 때를 가르킨다.
(MemberController.java)
package com.care.db.basic.controller;
import java.util.HashMap;
import java.util.Random;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.care.db.basic.dto.MemberDTO;
import com.care.db.basic.service.MailService;
import com.care.db.basic.service.MemberService;
@Controller
public class MemberController {
@Autowired private MemberService service;
// member 페이지 메일 인증번호 기능
@Autowired private MailService mailService;
@Autowired private HttpSession session;
@ResponseBody
@PostMapping(value="sendAuth", produces = "text/html; charset=UTF-8")
public String sendAuth(@RequestBody(required = false) String email) {
if(email == null) {
return "이메일을 입력하세요.";
}
Random r = new Random();
int begin = 0;
int end = 999999;
int ran = r.nextInt(end-begin+1) + begin;
String randomNumber = String.format("%06d", ran);
// 인증번호는 사용자별 정보이기에 session에 꼭 저장해야함.
session.setAttribute("randomNumber", randomNumber);
System.out.println("인증번호 : " + randomNumber);
mailService.sendMail(email, "[인증번호]", randomNumber);
return "인증번호를 이메일로 전송했습니다.";
}
@ResponseBody
@PostMapping(value="checkAuth", produces = "text/html; charset=UTF-8")
public String checkAuth(@RequestBody(required = false) String authNumber) {
String randomNumber = (String)session.getAttribute("randomNumber");
if(authNumber == null)
return "인증번호를 입력하세요.";
else if(randomNumber == null)
return "이메일을 입력 후 인증번호를 생성하세요.";
else if(authNumber.equals(randomNumber) )
return "인증 성공";
else
return "인증 실패";
}
@GetMapping("member")
public String member() {
return "member/member";
}
@PostMapping("member")
public String member(MemberDTO member, String confirmPw, Model model) {
String msg = service.member(member, confirmPw);
model.addAttribute("msg", msg);
if(msg.equals("가입 완료")) {
session.removeAttribute("randomNumber");
return "member/index";
}
return "member/member";
}
}
@ResponseBody는 member.jsp 페이지에서
매개변수로 @RequestBody를 이용한 것은 member.jsp 페이지에서 XMLHttpRequest()로 보내는 값이기 때문이다.
매개변수에 (required = false)는 받는 값이 null이여도 매개변수로 받아오도록 설정해준 것이다.
인증번호는 클라이언트별로 생성되는 값이 다르므로 서버에 전역변수(공통변수)로 설정하면 안되고,
각 클라이언트의 Session에 저장해두어 인증번호 확인하여야 한다.
(인증번호를 Session에 저장해두면 시간 설정을 하여 인증번호 시간제한을 할 수도 있다.)
가입 성공하면, Session으로 저장한 인증번호 지우는 코드를 넣어주면 된다.
'Programming > Spring' 카테고리의 다른 글
[AWS] Amazon EC2 인스턴스를 이용해 파일 업로드(연결)해보기 (0) | 2022.11.02 |
---|---|
[Spring] 카카오 Login API 사용하기 (0) | 2022.10.26 |
[Spring] 스프링을 시작하며...(2) Spring Legacy Project 세팅하기 (0) | 2022.10.24 |
[Spring] 스프링을 시작하며...(1) 스프링 개발환경 세팅하기 (0) | 2022.10.19 |