티스토리 뷰

https://youtube.com/playlist?list=PLRx0vPvlEmdAdWCQeUPnyMZ4PsW3dGuFB 

 

JSP 강의평가 웹 사이트 개발하기 (JSP Lecture Evaluation Service Development Tutorial)

 

www.youtube.com

 

JSP 강의평가 웹 사이트 개발하기 9강

회원가입 때 사용한 Email 인증과정을 만든다. 이 과정에서 가염처리와 해시처리를 다룬다. 가염처리는 정보를 가로챈 사람이 정보를 해독하는데 필요한 노력을 더 증가시키며 해시처리는 정보를 바로 노출시키지 않는 보안적인 부분이다.

 

 

  • SHA256.java : 가입할 때 입력한 이메일 주소를 해시처리한 값과 인증을 시도하는 이메일을 해시처리한 값을 비교해 사용자 인증을 하기 위함
  • Gmail.java : 개발자의 gmail과 연동해 이메일을 발송하기 위함
  • userRegisterAction.jsp : 회원가입 처리를 위함
  • emailSendAction.jsp : 이메일 인증 메세지를 보내기 위함
  • emailCheckAction.jsp : 사용자가 이메일 인증을 시도할 때 정상처리를 하기 위함

 

util/SHA256.java

// hash(Email) 을 위함
public class SHA256 {
	public static String getSHA256(String input) {
		StringBuffer result = new StringBuffer();
		try {
        		// 입력한 값에 Hash Algo 적용
			MessageDigest digest = MessageDigest.getInstance("SHA-256");
			/****** 가염 처리과정 ******/
			byte[] salt = "Hello Salt".getBytes();
			digest.reset();
			digest.update(salt);
			byte[] chars = digest.digest(input.getBytes("UTF-8")); // Hash 적용 값을 담아준다.
			/******* chars -> 16진수 String으로 변환 *******/
			for(int i = 0; i < chars.length; i++) {
				String hex = Integer.toHexString(0xff & chars[i]);
				if(hex.length() == 1) result.append("0"); // 항상 두 자리 16진수로
				result.append(hex);
			}
			
		}catch(Exception e) {
			e.printStackTrace();
		}
		return result.toString();
	}
}

가염처리 및 해시처리 과정이다. 항상 16진수로 반환하며, 해당 반환 내용을 통해 사용자 인증이 이루어진다.

 

util/Gmail.java

package util;

import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;

public class Gmail extends Authenticator{
	@Override
	protected PasswordAuthentication getPasswordAuthentication() {
		return new PasswordAuthentication("개발자의 gmail ID", "password");
	}
}

지정한 Gmail을 이용해 회원가입자들에게 발송한다. 앱 사용 허용과 같은 과정은 강의와 동일하니 생략한다.

 

userRegisterAction.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="user.UserDTO"%>
<%@ page import="user.UserDAO"%>
<%@ page import="util.SHA256"%>
<%@ page import="java.io.PrintWriter"%>

<%
	request.setCharacterEncoding("UTF-8");
	/* 로그인한 상태라면 가입을 진행할 수 없다. */
	String userID = null;
	if(session.getAttribute("userID") != null){
		userID = (String) session.getAttribute("userID");
	}
	if(userID != null){
		userID = (String) session.getAttribute("userID");
		PrintWriter script = response.getWriter();
		script.println("<script>");
		script.println("alert('이미 로그인 상태입니다.');");
		script.println("location.href = 'index.jsp'");
		script.println("</script>");
		script.close();
		return;
	}
	String userPassword = null;
	String userEmail = null;
	if(request.getParameter("userID") != null){
		userID = (String) request.getParameter("userID");
	}
	if(request.getParameter("userPassword") != null){
		userPassword = (String) request.getParameter("userPassword");
	}
	if(request.getParameter("userEmail") != null){
		userEmail = (String) request.getParameter("userEmail");
	}
	
	/********** 입력하지 않은 사항이 있을 때 처리 ***********/
	
	if(userID == null || userPassword == null || userEmail == null){
		PrintWriter script = response.getWriter();
		script.println("<script>");
		script.println("alert('입력을 다시 확인해주세요');");
		script.println("history.back();");
		script.println("</script>");
		script.close();
		return;
	}
	
	
	UserDAO userDAO = new UserDAO();
	int result = userDAO.join(new UserDTO(userID, userPassword, userEmail, SHA256.getSHA256(userEmail), false));
	if(result == -1){
		PrintWriter script = response.getWriter();
		script.println("<script>");
		script.println("alert('이미 존재하는 아이디입니다.');");
		script.println("history.back();"); 
		script.println("</script>");
		script.close();
	} else{
		session.setAttribute("userID", userID);    // ID 등록
		PrintWriter script = response.getWriter();
		script.println("<script>");
		script.println("location.href = 'emailSendAction.jsp'"); // 이메일 인증
		script.println("</script>");
		script.close();
	}
	
%>

userJoin.jsp 페이지에서 작성한 form 양식의 데이터가 userRegisterAction.jsp로 전달된다. 

session에서 userID값이 null 이 아니라면(로그인한 상태라면) 가입 진행이 불가능하다.

입력한 userID가 테이블에서 조회되면 가입이 불가능하며, 정상 가입이 진행되면 이메일 인증 페이지로 이동한다. 

 

emailSendAction.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@page import="javax.mail.Transport"%>
<%@page import="javax.mail.Message"%>
<%@page import="javax.mail.Address"%>
<%@page import="javax.mail.internet.InternetAddress"%>
<%@page import="javax.mail.internet.MimeMessage"%>
<%@page import="javax.mail.Session"%>
<%@page import="javax.mail.Authenticator"%>
<%@ page import="java.util.Properties"%>
<%@ page import="user.UserDTO"%>
<%@ page import="user.UserDAO"%>
<%@ page import="util.SHA256"%>
<%@ page import="util.Gmail"%>
<%@ page import="java.io.PrintWriter"%>

<%
	UserDAO userDAO = new UserDAO();
	String userID = null;
	if(session.getAttribute("userID") != null){
		userID = (String) session.getAttribute("userID");
	}
	if(userID == null){
		PrintWriter script = response.getWriter();
		script.println("<script>");
		script.println("alert('로그인을 해주세요');");
		script.println("location.href ='userLogin.jsp'");
		script.println("</script>");
		script.close();
		return;
	}
	
	boolean emailChecked = userDAO.getUserEmailChecked(userID);
	if(emailChecked){
		PrintWriter script = response.getWriter();
		script.println("<script>");
		script.println("alert('이미 인증이 완료된 회원입니다.');");
		script.println("location.href ='index.jsp'"); 
		script.println("</script>");
		script.close();
		return;
	} 
	
	// 사용자 인증 이메일 발송 내용
	String host = "http://localhost:8080/Lecture_Evaluation/";
	String from = "Gmail.java에 등록된 이메일";
	String to = userDAO.getUserEmail(userID);
	String subject = "강의평가 웹 사이트 이메일 인증 메일"; 
	String content = "링크에 접속해 이메일 인증을 진행해주세요." +
		"<a href='" + host + "emailCheckAction.jsp?code=" + new SHA256().getSHA256(to) + "'>이메일 인증하기</a>";
	
	// 이메일 전송 : SMTP 이용을 위함
	Properties p = new Properties();
	p.put("mail.smtp.user", from);
	p.put("mail.smtp.host", "smtp.googlemail.com"); // google SMTP 주소
	p.put("mail.smtp.port", "465");
	p.put("mail.smtp.starttls.enable", "true");
	p.put("mail.smtp.auth", "true");
	p.put("mail.smtp.debug", "true");
	p.put("mail.smtp.socketFactory.port", "465");
	p.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
	p.put("mail.smtp.socketFactory.fallback", "false");
	p.put("mail.smtp.ssl.protocols", "TLSv1.2"); // 추가된 코드
	p.put("mail.smtp.ssl.enable", "true");  // 추가된 코드

	try{
		Authenticator auth = new Gmail();
	    Session ses = Session.getInstance(p, auth);
	    ses.setDebug(true);
	    MimeMessage msg = new MimeMessage(ses); 
	    msg.setSubject(subject);		// 메일 제목
	    Address fromAddr = new InternetAddress(from); 	// 보내는 사람 정보
	    msg.setFrom(fromAddr);
	    Address toAddr = new InternetAddress(to);		// 받는 사람 정보
	    msg.addRecipient(Message.RecipientType.TO, toAddr);
	    msg.setContent(content, "text/html;charset=UTF-8");
	    Transport.send(msg); // 메세지 전송
	}catch(Exception e){
		e.printStackTrace();
		PrintWriter script = response.getWriter();
		script.println("<script>");
		script.println("alert('메일 전송 중 오류가 발생했습니다.');");
		script.println("history.back();"); 
		script.println("</script>");
		script.close();
	}
%>

HTML 코드는 생략, 2021년 9월 기준, 강의와 똑같이 코드를 작성하면 메일 전송이 이루어지지 않는다. 열심히 구글링한 결과 아래의 두 줄을 추가하면 emailSendAction이 정상적으로 동작한다.

 

p.put("mail.smtp.ssl.protocols", "TLSv1.2");
p.put("mail.smtp.ssl.enable", "true");

 

emailCheckAction.jsp

<!-- 사용자가 Email 인증 버튼을 눌렀을 때 처리해주는 페이지 -->
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="user.UserDAO"%>
<%@ page import="util.SHA256"%>
<%@ page import="java.io.PrintWriter"%>


<%
	request.setCharacterEncoding("UTF-8");
	UserDAO userDAO = new UserDAO();
	String code = null;
	if(request.getParameter("code") != null){
		code = request.getParameter("code");
	}
	
	String userID = null;
	
	if(session.getAttribute("userID") != null){
		userID = (String) session.getAttribute("userID");
	}
	if(userID == null){
		PrintWriter script = response.getWriter();
		script.println("<script>");
		script.println("alert('로그인 해주세요');");
		script.println("location.href = 'userLogin.jsp'");
		script.println("</script>");
		script.close();
		return;
	}
	
	// hash 처리한 결과를 비교해 결과 값 반환
	String userEmail = userDAO.getUserEmail(userID);
	boolean isRight = (new SHA256().getSHA256(userEmail).equals(code)) ? true : false;
	if(isRight == true){
		userDAO.setUserEmailChecked(userID);
		PrintWriter script = response.getWriter();
		script.println("<script>");
		script.println("alert('인증에 성공했습니다.');");
		script.println("location.href = 'index.jsp'");
		script.println("</script>");
		script.close();
		return;
	}else{
		PrintWriter script = response.getWriter();
		script.println("<script>");
		script.println("alert('잘못된 이메일 주소입니다.');");
		script.println("location.href = 'index.jsp'");
		script.println("</script>");
		script.close();
	}

%>

이메일 인증은 로그인한 상태에서만 진행가능하다. emailSendAction에 포함된 code 값 new SHA256().getSHA256(to) 과 테이블에서 조회한 new SHA256().getSHA256(userEmail)을 비교해 일치하면 인증에 성공한다.

 

 

회원가입 및 이메일 인증 진행

user 테이블 조회

 

회원가입 진행

테이블 조회

 

 

이메일 인증 과정

naver 메일함
인증링크 클릭
테이블 조회

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
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
글 보관함