JSP

 

 

 

진행 순서는 다음과 같다.

 AdminIndexAction  ->  main.jsp(로그인 폼)  ->adminLoginProc.jsp ->  AdminLoginAction (로그인 액션)  -> adminLoginProc.jsp

-> 로그인 후 상품 목록 adminLoginProc.jsp

 

 

AdminIndexAction

package net.macaronics.web.admin.controller;

import java.io.IOException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.RSAPublicKeySpec;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.macaronics.web.controll.action.Action;

public class AdminIndexAction implements Action {

	public static final int KEY_SIZE = 1024;
	 
	@Override
	public void execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String url = "admin/main.jsp";
		
		try {
			KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
			generator.initialize(KEY_SIZE);

			KeyPair keyPair = generator.genKeyPair();
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");

			PublicKey publicKey = keyPair.getPublic();
			PrivateKey privateKey = keyPair.getPrivate();

			HttpSession session = request.getSession();
			// 세션에 공개키의 문자열을 키로하여 개인키를 저장한다.
			session.setAttribute("__rsaPrivateKey__", privateKey);

			// 공개키를 문자열로 변환하여 JavaScript RSA 라이브러리 넘겨준다.
			RSAPublicKeySpec publicSpec = (RSAPublicKeySpec) keyFactory.getKeySpec(publicKey, RSAPublicKeySpec.class);

			String publicKeyModulus = publicSpec.getModulus().toString(16);
			String publicKeyExponent = publicSpec.getPublicExponent().toString(16);

			request.setAttribute("publicKeyModulus", publicKeyModulus);
			request.setAttribute("publicKeyExponent", publicKeyExponent);

			request.getRequestDispatcher(url).forward(request, response);
		} catch (Exception ex) {
			throw new ServletException(ex.getMessage(), ex);
		}
	}

	
	
}


 

 

main.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>    
<%@ taglib uri="http://www.owasp.org/index.php/Category:OWASP_CSRFGuard_Project/Owasp.CsrfGuard.tld" prefix="csrf" %>    
<!DOCTYPE html>
<html>
  <head>
    <title>Admin Login</title>
    <!-- Bootstrap -->
    <link href="../Bootstrap-Admin/bootstrap/css/bootstrap.min.css" rel="stylesheet" media="screen">
    <link href="../Bootstrap-Admin/bootstrap/css/bootstrap-responsive.min.css" rel="stylesheet" media="screen">
    <link href="../Bootstrap-Admin/assets/styles.css" rel="stylesheet" media="screen">
     <!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
    <!--[if lt IE 9]>
      <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->
    <script src="../Bootstrap-Admin/vendors/modernizr-2.6.2-respond-1.1.0.min.js"></script>
    

<!-- script 태그에서 가져오는 자바스크립트 파일의 순서에 주의해야한다! 순서가 틀릴경우 자바스크립트 오류가 발생한다. -->
<script type="text/javascript" src="${request.getContextPath() }/js/rsa/jsbn.js"></script>
<script type="text/javascript" src="${request.getContextPath() }/js/rsa/rsa.js"></script>
<script type="text/javascript" src="${request.getContextPath() }/js/rsa/prng4.js"></script>
<script type="text/javascript" src="${request.getContextPath() }/js/rsa/rng.js"></script>
<script type="text/javascript" src="${request.getContextPath() }/js/login.js"></script>

  </head>
  <body id="login">
    <div class="container">

      <form class="form-signin">
       
         <c:choose>
           <c:when test='${param.message=="error" }'>
            <h3 class="form-signin-heading  text-center">
             <small style="color:red;">아이디와 비밀번호가 일치하지 않습니다.</small>
             </h3>
           </c:when>
         	<c:otherwise>
         	 <h2 class="form-signin-heading  text-center">
         		관리자 로그인
         	</h2>
         	</c:otherwise>
         </c:choose>
         
        
        <input type="text" class="input-block-level" placeholder="아이디" id="username"  value="admin">
        <input type="password" class="input-block-level" placeholder="비밀번호" id="password" value="1111">
        <label class="checkbox">
         
        </label>
        <div class="text-center"><button class="btn btn-large btn-primary" 
        type="button" onclick="validateEncryptedForm(); return false;">로그인</button></div>
      </form>


    <input type="hidden" id="rsaPublicKeyModulus" value="${publicKeyModulus}" />
    <input type="hidden" id="rsaPublicKeyExponent" value="${publicKeyExponent}" />
  <csrf:form  id="securedLoginForm" name="securedLoginForm"
     action="${request.getContextPath() }/admin/adminLoginProc.jsp" method="post" style="display: none;">
       <input type="hidden" name="securedUsername" id="securedUsername" value="" />
       <input type="hidden" name="securedPassword" id="securedPassword" value="" />
 
   </csrf:form>




    </div> <!-- /container -->
    <script src="../Bootstrap-Admin/vendors/jquery-1.9.1.min.js"></script>
    <script src="../Bootstrap-Admin/bootstrap/js/bootstrap.min.js"></script>
  </body>
</html>

 

 

 

AdminLoginAction

package net.macaronics.web.admin.controller;

import java.io.IOException;
import java.math.BigInteger;
import java.security.PrivateKey;

import javax.crypto.Cipher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import net.macaronics.web.admin.controller.dao.AdminDAO;
import net.macaronics.web.controll.action.Action;
import net.macaronics.web.dao.MemberDAO;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class AdminLoginAction  {
	 final static Logger logger =LogManager.getLogger(AdminLoginAction.class);
	 

	  // 암호화된 비밀번호를 복호화 한다.
    public boolean processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String securedUsername = request.getParameter("securedUsername");
        String securedPassword = request.getParameter("securedPassword");
 
         
        // 파라미터로 넘어온 값
        logger.info("securedUsername: {}  ",securedUsername );
        logger.info("securedPassword: {}", securedPassword);
         
        HttpSession session = request.getSession();
        PrivateKey privateKey = (PrivateKey) session.getAttribute("__rsaPrivateKey__");
        session.removeAttribute("__rsaPrivateKey__"); // 키의 재사용을 막는다. 항상 새로운 키를 받도록 강제.
 
        if (privateKey == null) {
            throw new RuntimeException("암호화 비밀키 정보를 찾을 수 없습니다.");
        }
 
        try {
            String username = decryptRsa(privateKey, securedUsername);
            String password = decryptRsa(privateKey, securedPassword);
            request.setAttribute("username", username);
            request.setAttribute("password", password);
             
            // 파라미터로 넘어온 setAttribute 로 가져오기 값
            logger.info("request.getAttribute(): {}, {}   ",username,  password);     
            return confirm(username,password);
            
        } catch (Exception ex) {
            throw new ServletException(ex.getMessage(), ex);
        }        
     
    }
 
     //비밀번호 아이디 확인
     private boolean confirm(String id , String pwd){
    	 AdminDAO adminDAO= AdminDAO.getInstnce();
         return adminDAO.workerCheck(id, pwd); 
     }
     
     
     
     
    private String decryptRsa(PrivateKey privateKey, String securedValue) throws Exception {
        System.out.println("will decrypt : " + securedValue);
        Cipher cipher = Cipher.getInstance("RSA");
        byte[] encryptedBytes = hexToByteArray(securedValue);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
        String decryptedValue = new String(decryptedBytes, "utf-8"); // 문자 인코딩 주의.
        return decryptedValue;
    }
 
     
    // 16진 문자열을 byte 배열로 변환한다.
    
    public static byte[] hexToByteArray(String hex) {
        if (hex == null || hex.length() % 2 != 0) {
            return new byte[]{};
        }
 
        byte[] bytes = new byte[hex.length() / 2];
        for (int i = 0; i < hex.length(); i += 2) {
            byte value = (byte)Integer.parseInt(hex.substring(i, i + 2), 16);
            bytes[(int) Math.floor(i / 2)] = value;
        }
        return bytes;
    }
 
    
     // BigInteger를 사용해 hex를 byte[] 로 바꿀 경우 음수 영역의 값을 제대로 변환하지 못하는 문제가 있다.
    
    @Deprecated
    public static byte[] hexToByteArrayBI(String hexString) {
        return new BigInteger(hexString, 16).toByteArray();
    }
 
        public static String base64Encode(byte[] data) throws Exception {
        BASE64Encoder encoder = new BASE64Encoder();
        String encoded = encoder.encode(data);
        return encoded;
    }
 
    public static byte[] base64Decode(String encryptedData) throws Exception {
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] decoded = decoder.decodeBuffer(encryptedData);
        return decoded;
    }
 
}

 

adminLoginProc.jsp

<%@page import="net.macaronics.web.admin.controller.AdminLoginAction"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%

    AdminLoginAction  login =new AdminLoginAction();
	String url="MacaronicsServlet?command=admin_login_form&message=error";
	
	boolean result =login.processRequest(request, response);
	System.out.print("반환 값 :  " + result);
	 if(result){
		 System.out.print(request.getAttribute("username"));
			 //로그인 성공
			 session.setAttribute("wokerid", request.getAttribute("username"));
			// url="MacaronicsServlet?command=admin_product_list";
			 url="adminProduct/admin_product_list.jsp";
	}
	response.sendRedirect(url);

%>    

 

 

 

DAO

package net.macaronics.web.admin.controller.dao;

import java.util.HashMap;
import java.util.Map;

import org.apache.ibatis.session.SqlSession;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import config.MybatisService;

public class AdminDAO {
 
	 private static final Logger logger =LogManager.getLogger(AdminDAO.class);
	 
	 private SqlSession sqlSession;
	 
	 private static AdminDAO instance ;
	 
	 private AdminDAO(){
		 
	 }
	 
	 public static AdminDAO getInstnce(){
		 if(instance ==null){
			 instance =new AdminDAO();
		 }
		 return instance;
	 }
	 
	 
	 //비밀번호 체크
	 public boolean workerCheck(String id, String pwd){
		 int result=0;
		 try{
			 sqlSession=MybatisService.getFactory().openSession();
			 Map<String, Object> map=new HashMap<>();
			 map.put("id", id);
			 map.put("pwd", pwd);
			 result=sqlSession.selectOne("admin.workerCheck",map);
		 }catch(Exception e){
			 e.printStackTrace();
		 }finally{
			 MybatisService.sessionClose(sqlSession);
		 }
	
		 //0보다 크면 로그인 성공
		 return result >0 ? true :false;
	 }
	
	
	 
	 
	 
}

 

 

Mybatis

admin.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="admin">
	<!-- id="태그의 식별자" resultType="sql 명령어의 리턴타입(레코드의 자료형)" 샵{변수} => 입력매개변수 -->

	<select id="workerCheck" resultType="int">
		select count(*) from TBL_ADMIN where id =#{id} and pwd=#{pwd}
	</select>


</mapper>


	
	
	

 

 

로그인 성공시

 

 

 

제작 : macaronics.net - Developer  Jun Ho Choi

소스 :  https://github.com/braverokmc79/jsp_sin

 

${request.getContextPath() } 처리를 안한 부분이 있으므로 

루트 설정( http://macaronics.net/index.php/m01/jsp/view/1352)    및 server.xml  에서 DB 컨넥션 설정은 필수 설정이다.

 

 

about author

PHRASE

Level 60  라이트

낭중지추( 囊中之錐 ). 송곳이 주머니 속에 들어 있으면 반드시 그 끝이 나오듯이 재능이 있으면 언젠가는 그 기량을 나타낸다는 말. -사기

댓글 ( 4)

댓글 남기기

작성