본문 바로가기
개발/JSP

[JSP] Oracle 기반 로그인 페이지 구현&해시 적용&비밀번호 임계값 설정, 임시 비밀번호 1회 사용 제한

by m_.9m 2022. 6. 29.

목차

     

     

     

    [파일 목록]

     

    [설정 환경]

    이클립스

     

    [index.jsp]

     

     

    [UserDAO.java]

    package user;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    
    public class UserDAO {
    	
    	private Connection conn; //connection
    	private ResultSet rs;      
    	
    	 public UserDAO(){ 
    	        try {
    				String driverName = "oracle.jdbc.driver.OracleDriver";
    				String dbURL = "jdbc:oracle:thin:@ip:1521:XE";
    				String dbID = "";
    				String dbPassword = "";
    				
    				Class.forName(driverName);
    				conn = DriverManager.getConnection(dbURL, dbID, dbPassword);
    				
    				System.out.println("-----------------------------------------"
    						+ "--------------------------------\n -> USER DB START.");
    	            
    	        } catch (Exception e) {
    	            e.printStackTrace();
    	        }
    	    }
    	    
    	
    	public int login(String userID, String userPassword) {
    		System.out.println("-> USER LOGIN.\n");
    		String SQL="SELECT userPassword FROM USERS WHERE userID = ? AND PWCOUNT > 0 AND (pwtemp = 1 OR Pwavailable = 1)";
    		try {
    			PreparedStatement pstmt = conn.prepareStatement(SQL);
    			pstmt.setString(1,userID);
    			SHAHashDemo SHAHash = new SHAHashDemo();//하나의 인스턴스
    			String pw= SHAHash.byteDigest(userPassword);
    			rs=pstmt.executeQuery();
    			if(rs.next()) {
    				if(rs.getString(1).equals(pw))
    					return 1;
    				else
    					return 0; 
    			}
    			return -1;
    		} catch(Exception e) {
    			e.printStackTrace();
    		}
    		return -2; 
    	}
    	
    	//pwcount는 임계값이며 잠김시 pwcount로 기존pw 사용 절대 불가, 임시 비밀번호 발급 시 pwtemp1, available0 초기화시 pwcount5, pwtemp0, available1 
    
    	public int userpwtemp(String userID) {
    		System.out.println("-> temp PW.\n");
    		String SQL="UPDATE USERS SET pwavailable=0 ,pwtemp = 0, pwcount=5 WHERE USERID= ? AND pwtemp = 1";
    		try {
    			PreparedStatement pstmt = conn.prepareStatement(SQL);
    			pstmt.setString(1,userID);
    			rs=pstmt.executeQuery();
    			if(rs.next()) {
    				return 1;
    			}else {
    					return 0; 
    				}
    		} catch(Exception e) {
    			e.printStackTrace();
    		}
    		return -2; 
    	}
    	public int pwcount(String userID) {
    		System.out.println("-> USER PW CONUT.\n");
    		String SQL="UPDATE USERS SET PWCOUNT=PWCOUNT-1 WHERE USERID= ?";
    		try {
    			PreparedStatement pstmt = conn.prepareStatement(SQL);
    			pstmt.setString(1,userID);
    			return pstmt.executeUpdate();
    			}
    		catch(Exception e) {
    			e.printStackTrace();
    		}
    		return -1;
    	}
    
    // 비밀번호 변경
    	public int Update(String userPassword, String useremail) {
    		String SQL = "update USERS set userPassword=?, Pwtemp=1, Pwavailable=0 Where useremail=?";
    		try {
    			PreparedStatement pstmt = conn.prepareStatement(SQL);
    			userPassword = userPassword.split(":")[1];
    			SHAHashDemo SHAHash = new SHAHashDemo();//하나의 인스턴스
    			String pw= SHAHash.byteDigest(userPassword);
    			pstmt.setString(1, pw);
    			pstmt.setString(2, useremail);
    			return pstmt.executeUpdate();
    		} catch(Exception e) {
    			e.printStackTrace();//예외처리
    		}
    		return -1;//데이터베이스 오류
    	}

     

    [User.java]

    package user;
    
    public class User {
    	private String userID;
    	private String userPassword;
    	private String userName;
    	private String userGender;
    	private String userEmail;
    	
    	public String getUserID() {
    		return userID;
    	}
    	public void setUserID(String userID) {
    		this.userID = userID;
    	}
    	public String getUserPassword() {
    		return userPassword;
    	}
    	public void setUserPassword(String userPassword) {
    		this.userPassword = userPassword;
    	}
    	public String getUserName() {
    		return userName;
    	}
    	public void setUserName(String userName) {
    		this.userName = userName;
    	}
    	public String getUserGender() {
    		return userGender;
    	}
    	public void setUserGender(String userGender) {
    		this.userGender = userGender;
    	}
    	public String getUserEmail() {
    		return userEmail;
    	}
    	public void setUserEmail(String userEmail) {
    		this.userEmail = userEmail;
    	}
    	
    }

     

    [SHAHashDemo.java]

    (필요 파일 정확히 어느 파일인지 몰라서 다 첨부)

    commons-codec-1.15-sources.jar
    0.35MB
    commons-codec-1.15.jar
    0.34MB
    commons-codec-1.15-javadoc.jar
    0.52MB

    package user;
    
    import org.apache.commons.codec.digest.DigestUtils;
    
    import java.io.*;
    import java.nio.charset.StandardCharsets;
    
    public class SHAHashDemo {
        public static void main(String[] args) {
            SHAHashDemo demo = new SHAHashDemo();
            demo.byteDigest(null);
            //demo.inputStreamDigest();
            //demo.stringDigest();
        }
    
        /**
         * Calculates SHA-1 digest from byte array.
         */
        public String byteDigest(String pw) {
            System.out.println("SHAHashDemo.byteDigest");
            byte[] data = pw
                    .getBytes(StandardCharsets.UTF_8);
            String digest = DigestUtils.sha1Hex(data);
            System.out.println("Digest          = " + digest);
            System.out.println("Digest.length() = " + digest.length());
            
            return digest;
        }
    
        /**
    
        private void inputStreamDigest() {
            System.out.println("SHAHashDemo.inputStreamDigest");
            String data = System.getProperty("user.dir") + "/data.txt";
            File file = new File(data);
            try {
                InputStream is = new FileInputStream(file);
                String digest = DigestUtils.sha1Hex(is);
                System.out.println("Digest          = " + digest);
                System.out.println("Digest.length() = " + digest.length());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    
        private void stringDigest() {
            System.out.println("SHAHashDemo.stringDigest");
            String data = "This is just a simple data message for SHA digest demo.";
            String digest = DigestUtils.sha1Hex(data);
            System.out.println("Digestc          = " + digest);
            System.out.println("Digest.length() = " + digest.length());
        }
        */
        
    }

     

    [SMTPAuthenticator.java]

    (필요 파일 정확히 어느 파일인지 몰라서 다 첨부)

    smtp.jar
    0.05MB
    pop3.jar
    0.04MB
    log4sql.jar
    0.08MB
    javax.mail-api-1.4.7.jar
    0.18MB
    imap.jar
    0.17MB
    gimap.jar
    0.01MB
    dsn.jar
    0.02MB
    cos.jar
    0.05MB
    mailapi.jar
    0.27MB
    mail.jar
    0.44MB

    package mail;
    
    import javax.mail.Authenticator;
    import javax.mail.PasswordAuthentication;
    
    
    public class SMTPAuthenticatior extends Authenticator{
    
        @Override
        protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication("아이디","비밀번호");
        }
    }

     

    네이버 메일 설정 참고 : https://smujihoon.tistory.com/96

     

    [login.jsp]

     

    <%@ page language="java" contentType="text/html; charset=utf-8"
        pageEncoding="utf-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width-device-width">
    <link rel="stylesheet" href="css/bootstrap.css">
    <link href="css/style.css" rel="stylesheet" type="text/css" />
    <title>JSP 게시판 웹 사이트</title>
    </head>
    <body>
    	<nav class="navbar navbar-default">
    	<div class="navbar-header">
    		<button type="button" class="navbar-toggle collapsed"
    			data-toggle="collapse" data-target="#bs-example-navbar-collapse-1"
    			aria-expanded="false">
    		</button>
    	<h2 class="navbar-brand">JSP web-site</h2>
            <ul class="nav navbar-nav">
            <li><a href="index.jsp;"> MAIN </a></li>
            <li><a href="login.jsp;"> LOGIN </a></li>
            <li><a href="member.jsp;"> JOIN US </a></li>
    		</ul>
    	</div>
    	</nav>
    	 <form class=login_box action="loginAction.jsp" method="post">
        <h1>로그인</h1>
        비밀번호 5회 이상 틀릴 시 기존 비밀번호는 사용하실 수 없습니다.<br>
        비밀번호 찾기를 통해 새 암호를 설정하신 후 계정을 사용하시기 바랍니다.
      <input name=userID type="text" placeholder="아이디를 입력해 주세요."   maxlength="40">
      <input name=userPassword type="password" placeholder="비밀번호를 입력해 주세요." maxlength="14">
      <a href="javascript:void(0);" onclick="findpw();" style="margin-left:80%;">비밀번호 찾기</a> 
      <div class="normal-area">
      <button id=button_login name="button" class="primary" style="background: #fff;"><span style="color:">로그인</span></button>
      <button id=button_login onclick="window.location.href='member.jsp'" id=button_member name="button" class="primary" style="background: #ffe4e1;"><span style="color:black">회원이 아니신가요? 가입하기</span></button>
        </div></form>
    	<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
    	<script src="js/bootstrap.js"></script>
    	 <script>function findpw(){
    		 			url="findpw.jsp";
    					window.open(url,"chkid","width=600,height=300,top=250,left=500");
    	    			window.name="parentform";
    	    }</script>
    </body>

     

     

    [loginAction.jsp]

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ page import="user.UserDAO" %>
    <%@ page import="user.User" %>
    <%@ page import="java.io.PrintWriter" %>
    <% request.setCharacterEncoding("UTF-8"); %>
    <jsp:useBean id="user" class="user.User" scope="page" />
    <jsp:setProperty name="user" property="userID"/>
    <jsp:setProperty name="user" property="userPassword" />
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>JSP 게시판 웹 사이트</title>
    </head>
    <body>
    <%
    	  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 = 'main.jsp'");
                script.println("</script>");
            }
            
    		UserDAO userDAO=new UserDAO();//하나의 인스턴스
    		int result=userDAO.login(user.getUserID(), user.getUserPassword());//페이지에 입력된 아이디와 비번을 login함수에 넣어줌
    		if(result==1){
    
    			int pwresult=userDAO.userpwtemp(user.getUserID());
    			if(pwresult==1){
    				PrintWriter script = response.getWriter();
    				session.setAttribute("userID", user.getUserID());
    				script.println("<script>");
    	            script.println("alert('임시 비밀번호입니다. 초기화 부탁드립니다.')");
    	            script.println("location.href = 'Mypage.jsp'");
    				script.println("</script>");
    			}
    			else{
    
    			session.setAttribute("userID", user.getUserID());
    			PrintWriter script = response.getWriter();
    			script.println("<script>");
                script.println("location.href = 'main.jsp'");
    			script.println("</script>");
    		
    		}}
    		else{
    			int pwcount =userDAO.pwcount(user.getUserID());
    			PrintWriter script = response.getWriter();
    			script.println("<script>");
    			script.println("alert('로그인 실패하였습니다.')");
    			script.println("location.href = 'index.jsp'");
    			script.println("</script>");
    		}
    	%>
    </body>

     

    **비밀번호 임계값 설정

     

    [findpw.jsp]

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    	pageEncoding="UTF-8"%>
    <%@ page import="user.UserDAO" %>
    <%@ page import="user.User" %>
    <%@ page import="java.io.PrintWriter"%>
    <jsp:useBean id="user" class="user.User" scope="page" />
    <jsp:setProperty name="user" property="userPassword"/>
    <jsp:setProperty name="user" property="userEmail"/>
    
    
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    	<%  
    	
    		String userPassword ="";
    		for (int i = 0; i < 12; i++) {
    			userPassword += (char) ((Math.random() * 26) + 97);
    		}
    
    
    	%>
    	<div>
    		<form action="sendMail.jsp" method="post">
    			<table>
    				<tr><th colspan="2"><h3>임시 비밀번호 발급</h3></th></tr>
    				<td>비밀번호 변경 시 임시 비밀번호의 사용은 1회로 제한됩니다.<br> 반드시 초기화 후 사용해주시기 바랍니다.</td>
    				<tr><td></td><td><input type="hidden" name="from" value="내이메일@naver.com" /></td></tr>
    				<tr><td>가입하신 이메일 주소를 입력하세요.<br></td></tr>
    				<tr><td><input type="text" name="useremail" /></td></tr>
    				<tr><td></td><td><input type="hidden" name="subject" value="new temp password"/></td></tr>
    				<tr><td></td><td><input type="hidden" name="content" id="content" style="width:170px; height:200px;" value="new temp password:<%=userPassword%>"/></td></tr>
    				<tr><td colspan="2" style="text-align:right;"><input type="submit" value="메일 전송"/></td></tr>
    			</table>
    		</form>
    	</div>
    </body>
    </html>

     

     

    [sendMail.jsp]

    <%@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="mail.SMTPAuthenticatior"%>
    <%@page import="javax.mail.Authenticator"%>
    <%@page import="java.util.Properties"%>
    <%@page import="user.UserDAO"%>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <jsp:useBean id="user" class="user.User" scope="page" />
    <jsp:setProperty name="user" property="userEmail"/>
    <jsp:setProperty name="user" property="userPassword" />
    <%
    
    request.setCharacterEncoding("utf-8");
    
    String from = request.getParameter("from");
    String to = request.getParameter("useremail");
    String subject = request.getParameter("subject");
    String content = request.getParameter("content");
    
    UserDAO userDAO=new UserDAO();//하나의 인스턴스
    int result=userDAO.Update(content, to);
    
    
    Properties p = new Properties(); // 정보를 담을 객체
    
    p.put("mail.smtp.host","smtp.naver.com"); // 네이버 SMTP
    p.put("mail.smtp.port", "465");
    p.put("mail.smtp.ssl.enable", "true");
    p.put("mail.smtp.ssl.trust","smtp.naver.com");
    p.put("mail.smtp.auth", "true");
    p.put("mail.smtp.debug", "true");
    p.put("mail.smtp.ssl.protocols", "TLSv1.2");
    p.put("mail.smtp.socketFactory.port", "465");
    p.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
    p.put("mail.smtp.socketFactory.fallback", "false");
    // SMTP 서버에 접속하기 위한 정보들
    
    try{
        Authenticator auth = new SMTPAuthenticatior();
        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();
        out.println("<script>alert('Send Mail Failed..');window.close();</script>");
        // 오류 발생시 뒤로 돌아가도록
        return;
    }
    
    out.println("<script>alert('Send Mail Success!!');window.close();</script>");
    // 성공 시
    %>