본문 바로가기
학습/JSP

31. 파일 업로드(메소드 분리와 js파일 외부로 빼기)와 회원가입 & 로그인 & 비밀번호 암호화

by Elfen Lied 2022. 12. 9.
반응형

30번 글( https://simfairy.tistory.com/272 )에서 했던 코드를 리펙토링함

  • BoardController에 있는 몇몇 태그들을 FileUpload 클래스에 따로 모아서 관리함

 

 

- sql

board_tbl

CREATE TABLE BOARD_TBL(
    BNO NUMBER(10) PRIMARY KEY,
    TITLE VARCHAR2(500) NOT NULL,
    CONTENT VARCHAR2(4000) NOT NULL,
    WRITER VARCHAR2(100) NOT NULL,
    imageFileName VARCHAR2(100),
    WRITEDATE DATE DEFAULT SYSDATE
);

 

t_member

CREATE TABLE T_MEMBER(
    MNO INT PRIMARY KEY,
    ID VARCHAR2(50) NOT NULL UNIQUE,
    PWD VARCHAR2(100),
    NAME VARCHAR2(50),
    EMAIL VARCHAR2(200),
    JOINDATE DATE DEFAULT SYSDATE
);

-- 시퀀스
CREATE SEQUENCE MNO_SEQ;

 

- com.controller 패키지 BoardController

package com.controller;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.common.FileUpload;
import com.dao.BoardDAO;
import com.domain.BoardVO;
import com.service.BoardService;

@WebServlet("/board/*")
public class BoardController extends HttpServlet {
	private BoardService service;
	private FileUpload multiReq;
	
	@Override
	public void init() throws ServletException {
		BoardDAO dao = new BoardDAO();
		service = new BoardService(dao);
		multiReq = new FileUpload("board/");
	}
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doHandle(request, response);
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doHandle(request, response);
	}
	private void doHandle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String contextPath = request.getContextPath();
		String pathInfo = request.getPathInfo();
		final String PREFIX = "/WEB-INF/views/board/";
		final String SUFFIX = ".jsp";
		
		RequestDispatcher rd = null;
		String nextPage = null;
		
		if(pathInfo == null || pathInfo.equals("/") || pathInfo.equals("/list")) {
			List<BoardVO> boardList = service.boardList();
			request.setAttribute("list", boardList);
			nextPage = "list";
		} else if(pathInfo.equals("/detail")) {
			String paramBno = request.getParameter("bno");
			int bno = Integer.parseInt(paramBno);
			BoardVO findBoard = service.findBoard(bno);
			request.setAttribute("board", findBoard);
			nextPage = "detail";
		} else if(pathInfo.equals("/writeForm")) {
			nextPage = "writeForm";
		} else if(pathInfo.equals("/write")) {
			Map<String, String> req = multiReq.getMultipartRequest(request);
			String imageFileName = req.get("imageFileName");
			
			BoardVO vo = BoardVO.builder()
					.title(req.get("title"))
					.content(req.get("content"))
					.writer(req.get("writer"))
					.imageFileName(req.get("imageFileName")).build();
			int boardNo = service.addBoard(vo);
			
			if(imageFileName != null && imageFileName.length() > 0) {
				multiReq.uploadImage(boardNo, imageFileName);
			}
			
			response.sendRedirect(contextPath + "/board");
			return;
		} else if(pathInfo.equals("/modBoard")) {
			Map<String, String> req = multiReq.getMultipartRequest(request);
			String paramBno = req.get("bno");
			int bno = Integer.parseInt(paramBno);
			String title = req.get("title");
			String content = req.get("content");
			String imageFileName = req.get("imageFileName");
			
			BoardVO vo = BoardVO.builder()
					.bno(bno)
					.title(title)
					.content(content)
					.imageFileName(imageFileName).build();
			service.modBoard(vo);
			
			if(imageFileName != null) {
				String originFileName = req.get("originFileName");
				
				multiReq.uploadImage(bno, imageFileName);
				if(originFileName != null) {
					multiReq.deleteOriginImage(paramBno, originFileName);
				}
			}
			response.sendRedirect(contextPath + "/board");
			return;
		} else if(pathInfo.equals("/removeBoard")) {
			Map<String, String> req = multiReq.getMultipartRequest(request);
			String paramBno = req.get("bno");
			int bno = Integer.parseInt(paramBno);
			service.removeBoard(bno);
			multiReq.deleteAllImage(bno);
			response.sendRedirect(contextPath + "/board");
			return;
		} else {
			System.out.println("존재하지않음");
			return;
		}
		rd = request.getRequestDispatcher(PREFIX + nextPage + SUFFIX);
		rd.forward(request, response);
	}

}

 

 

- com.common 패키지 FileUpload 클래스 생성

package com.common;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;

public class FileUpload {
	
	private static final String REPO_PATH = "c:/file_repo/";
	private String servicePathName;
	
	public FileUpload(String servicePathName) {
		this.servicePathName = servicePathName;
	}

	public Map<String, String> getMultipartRequest(HttpServletRequest request) {
		Map<String, String> paramMap = new HashMap<>();
		File currentDirPath = new File(REPO_PATH + servicePathName + "temp");
		
		DiskFileItemFactory factory = new DiskFileItemFactory();
		ServletFileUpload repository = new ServletFileUpload(factory);
		repository.setFileSizeMax(1024 * 1024 * 10);
		
		try {
			List<FileItem> items = repository.parseRequest(request);
			for(FileItem item : items) {
				if(item.isFormField()) {
					paramMap.put(item.getFieldName(), item.getString("utf-8"));
				} else {
					if(item.getSize() > 0) {
						String fileName = item.getName();
						paramMap.put(item.getFieldName(), fileName);
						File uploadFile = new File(currentDirPath, fileName);
						item.write(uploadFile);
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return paramMap;
	}
	
	// 새로운 이미지 업로드
	public void uploadImage(int no, String imageFileName) throws IOException {
		File srcFile = new File(REPO_PATH + servicePathName + "temp", imageFileName);
		File destFile = new File(REPO_PATH + servicePathName + no);
		destFile.mkdirs();
		FileUtils.moveFileToDirectory(srcFile, destFile, false);
	}
	
	// 기존 이미지 삭제
	public void deleteOriginImage(String no, String originFileName) {
		File oldFile = new File(REPO_PATH + servicePathName + no + "/" + originFileName);
		oldFile.delete();
	}
	
	// 모든 이미지 삭제
	public void deleteAllImage(int no) throws IOException {
		File targetDir = new File(REPO_PATH + servicePathName + no);
		if(targetDir.exists()) {
			FileUtils.deleteDirectory(targetDir);
		}
	}
}

 

 

- com.common 패키지 FileDownload 수정

String path 변수 추가

기존 String bno 부분을 no로 바꿔줌

경로 부분에 bno를 no로 바꿔줌

package com.common;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/fileDownload")
public class FileDownload extends HttpServlet {
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doHandle(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doHandle(request, response);
	}

	private void doHandle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String fileRepo = "c:/file_repo";
		String no = request.getParameter("no");
		String path = request.getParameter("path");
		String fileName = request.getParameter("imageFileName");
		File downloadFile = new File(fileRepo + "/" + path + "/" + no, fileName);
		
		fileName = URLEncoder.encode(fileName, "utf-8");
		response.setHeader("Cache-Control", "no-cache");
		response.addHeader("Content-disposition", "attachment; fileName=" + URLEncoder.encode(fileName, "utf-8"));
		
		try (
			OutputStream out = response.getOutputStream();
			InputStream in = new FileInputStream(downloadFile);
		){
			byte[] buffer = new byte[1024 * 8];
			int count = 0;
			while ((count = in.read(buffer)) != -1) {
				out.write(buffer, 0, count);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

 

- detail.jsp 파일 수정

table 안에 첨부이미지쪽 img 태그에 있는 <img class="originImg" src="${contextPath}~~~~ 이부분쪽에 수정됨

bno라고 되어있는 부분이 no로 바뀌고 마지막에 &path=board 가 추가됨

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ include file="../layout/header.jsp" %>
<script src="${contextPath}/resources/js/detail.js"></script>

<div class="container">
	<div class="text-center jumbotron bg-light">
		<h1>게시글조회</h1>
	</div>
	<form id="viewForm" enctype="multipart/form-data">
		<table class="table">
			<tr>
				<th>글번호</th>
				<td>${board.bno }<input type="hidden" name="bno" value="${board.bno }"></td>
			</tr>
			<tr>
				<th>작성일</th>
				<td>${board.writeDate}</td>
			</tr>
			<tr>
				<th>작성일</th>
				<td>${board.writer}</td>
			</tr>
			<tr>
				<th>제목</th>
				<td><input type="text" name="title" class="form-control" value="${board.title}" readonly="readonly"></td>
			</tr>
			<tr>
				<th>내용</th>
				<td><textarea rows="10" name="content" class="form-control" readonly="readonly">${board.content}</textarea></td>
			</tr>
			<tr>
				<th>첨부이미지</th>
				<td colspan="3">
					<input type="file" name="imageFileName" class="form-control viewMode" >
					<div class="my-2">
						<c:if test="${not empty board.imageFileName }">
							<input type="hidden" name="originFileName" value="${board.imageFileName }">
							<div class="preview">
								<img class="originImg" src="${contextPath}/fileDownload?no=${board.bno}&imageFileName=${board.imageFileName}&path=board">
							</div>
						</c:if>
						<c:if test="${empty board.imageFileName }">
							<div class="preview">
								<p><b>등록된 이미지 없음</b></p>
							</div>
						</c:if>
					</div>
				</td>
			</tr>
			<tr>
				<td colspan="4">
					<c:if test="${auth.id eq board.writer}">
						<button type="button" class="btn btn-info toModForm">수정하기</button>
						<button type="button" class="btn btn-danger remove">삭제</button>
					</c:if>
					<button type="button" class="btn btn-secondary toList">목록</button>
				</td>
			</tr>
			<tr class="viewMode">
				<c:if test="${auth.id eq board.writer}">
					<td colspan="4">
						<button type="button" class="btn btn-info modify">수정</button>
						<button type="button" class="btn btn-danger backViewMode">취소</button>
					</td>
				</c:if>
			</tr>
		</table>
	</form>
	
</div>

<%@ include file="../layout/footer.jsp" %>

 

 

- js파일 외부로 빼기

webapp / resources / js / detail.js, list.js, common.js 생성

 

우선 header.jsp에 스크립트를 추가한다.

nav 태그를 하나더 추가

contextPath를 전역에서 쓸수 있게 만들어준다

common.js는 공통으로 사용하기 때문에 header.jsp에 작성함

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="contextPath" value="${pageContext.request.contextPath}" />
<c:set var="auth" value="${sessionScope.auth}"></c:set>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js" integrity="sha512-aVKKRRi/Q/YV+4mjoKBsE4x3H+BkegoM/em46NNlCqNTmUYADjBbeNefNxYV7giUp0VxICtqdrbqU7iVaeZNXA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"></script>
<script>const contextPath = "${contextPath}"</script>
<script src="${contextPath}/resources/js/common.js"></script>


</head>
<body>

<nav class="navbar navbar-expand-sm bg-warning navbar-light justify-content-between">
  <ul class="navbar-nav">
    <li class="nav-item active">
      <a class="nav-link" href="#">LOGO</a>
    </li>
    <li class="nav-item">
      <a class="nav-link" href="${contextPath }/board">List</a>
    </li>
    <li class="nav-item">
      <a class="nav-link" href="#">Link</a>
    </li>
  </ul>
  
  <!-- 로그인, 로그아웃 회원가입 -->
  <ul class="navbar-nav">
    <c:if test="${empty auth }">
	    <li class="nav-item"> <!-- 세션값이 없을 때 -->
	      <a class="nav-link" href="${contextPath }/member/joinForm">회원가입</a>
	    </li>
	    <li class="nav-item">
	      <a class="nav-link" href="${contextPath }/member/loginForm">로그인</a>
	    </li>
    </c:if>
    
  <c:if test="${not empty auth }"> <!-- 세션값이 있을 때 -->
    <li class="nav-item">
    	<span class="nav-link"><b>${auth.id }</b>님 로그인 중</span>
    </li>
    <li class="nav-item">
      <a class="nav-link" href="${contextPath }/member/myPage">나의정보보기</a>
    </li>
    <li class="nav-item">
      <a class="nav-link" href="${contextPath }/member/logout">로그아웃</a>
    </li>
  </c:if>
  </ul>
</nav>

 

 

- list.js

list.jsp에서 작성한 제이쿼리 코드를 잘라내서 붙여넣어주고 

백틱(`) 숫자 1 좌측에 있는 특수기호

백틱으로 contextPath를 수정해준다

모든 경로들 다 수정한다

$(function() {
	let listForm = $('#listForm');
	$('.title').on('click', function(e){
		e.preventDefault();
		// let bnoData = "<input type='hidden' name='bno' value='"+$(this).data('bno')+"'/>";
		let bnoData = "<input type='hidden' name='bno' value='"+$(this).attr('href')+"'/>";
		listForm.append(bnoData)
				.attr('action', `${contextPath}/board/detail`)
				.submit();
	});
});

 

 

- detail.js

마찬가지로 detail.jsp에서 제이쿼리 부분 잘라내서 옮겨주고

contextPath 가있는 모든 경로에 백틱을 감싸서 수정함

기존에 있는 따옴표는 지움

가장 아래쪽에 있었던 제이쿼리 코드 on('change', function) 로 된 코드는 삭제 - 미리보기 로직임

(common.js로 옮길것임)

$(function() {
	
	$('.viewMode').hide();
	
	let viewForm = $('#viewForm');
	let titleObj = $('input[name="title"]');
	let contentObj = $('textarea[name="content"]');
	let imageFile = "${board.imageFileName}";
	let pTag = $('.preview p').html; 
	
	let originImg = $('.originImg').clone();
	let titleVal = titleObj.val();
	let contentVal = contentObj.val();
	
	// 수정모드
	$('.toModForm').on('click', function() {
		$('input[name="title"], textarea[name="content"]').attr("readonly", false);
		$('.viewMode').show();
		$(this).closest('tr').hide();		
	});
	
	// 수정처리
	$('.modify').on('click', function() {
		viewForm.attr({
			'action' : `${contextPath}/board/modBoard`,
			'method' : 'post'
		}).submit();
	});
	
	
	// 삭제
	$('.remove').on('click', function() {
		viewForm.attr({
			'action' : `${contextPath}/board/removeBoard`,
			'method' : 'post' 
		}).submit();
	});
	
	// 뷰모드
	$('.backViewMode').on('click', function() {
		$('input[name="title"], textarea[name="content"]').attr("readonly", true);
		$('.viewMode').hide ();
		$(this).closest('tr').prev().show();
		$('.preview').html(originImg);
		$('input[type="file"]').val('');
		titleObj.val(titleVal);
		contentObj.val(contentVal);
		if(imageFile == '' || imageFile == null) {
			$('.preview').html(pTag);
		}
	});
	
	// 목록
	$('.toList').on('click', function() {
		viewForm.attr({
			'action' : `${contextPath}/board`,
			'method' : 'get'
		}).empty().submit();
	});
	
});

 

 

 

- common.js

imgTag 변수를 백틱 사용해서 수정

 

$(function() {
	$('input[type="file"]').on('change', function() {
		if(this.files[0]) {
			let reader = new FileReader();
			reader.onload = function(e) {
				let value = e.target.result;
				if(value.startsWith("data:image/")) {
					let imgTag = `<img src="${value}">`;
					$('.preview').html(imgTag);
				} else {
					alert('이미지 파일만 등록');
					$('input[name="imageFileName"]').val('');
					$('.preview').html('');
				}
			}
			reader.readAsDataURL(this.files[0]);
		}
	});
});

 

 

 

- com.controller 패키지 MemberController 서블릿 생성

package com.controller;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.dao.MemberDAO;
import com.domain.AuthVO;
import com.domain.MemberVO;
import com.service.MemberService;

@WebServlet("/member/*")
public class MemberController extends HttpServlet {
	private MemberService service;
	
	@Override
	public void init(ServletConfig config) throws ServletException {
		service = new MemberService(new MemberDAO());
	}
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doHandle(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doHandle(request, response);
	}

	private void doHandle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String contextPath = request.getContextPath();
		String pathInfo = request.getPathInfo();
		final String PREFIX = "/WEB-INF/views/member/";
		final String SUFFIX = ".jsp";
		
		RequestDispatcher rd = null;
		String nextPage = null;
	
		if(pathInfo.equals("/joinForm")) {	// 회원가입 폼
			nextPage = "joinForm";
		} else if(pathInfo.equals("/join")) { // 회원가입 처리
			String id = request.getParameter("id");
			String pwd = (String) request.getAttribute("pwd");
			String name = request.getParameter("name");
			String email = request.getParameter("email");
			
			MemberVO vo = MemberVO.builder()
					.id(id)
					.pwd(pwd)
					.name(name)
					.email(email).build();
			service.memberJoin(vo);
			response.sendRedirect(contextPath + "/board"); 
			return;
		} else if(pathInfo.equals("/loginForm")) { //로그인 폼
			nextPage = "loginForm";
		} else if(pathInfo.equals("/login")) { // 로그인 처리
			String id = request.getParameter("id");
			String pwd = (String) request.getAttribute("pwd");
			MemberVO vo = MemberVO.builder()
					.id(id).pwd(pwd).build();
			
			if(service.loginService(vo)) {
				HttpSession session = request.getSession();
				AuthVO authVO = new AuthVO();
				authVO.setId(vo.getId());
				session.setAttribute("auth", authVO);
				String userUri = (String) session.getAttribute("userUri");
				if(userUri != null) {
					session.removeAttribute("userUri"); // 세션을 비워서 로그인시 기존에 기억된 주소로 가지않게 막아줌
					response.sendRedirect(userUri);
					return;
				}
				response.sendRedirect(contextPath + "/board"); 
				return;
			} else {
				System.out.println("MemberController.login : 아이디 또는 비밀번호 틀림");
				return;
			}
		} else if(pathInfo.equals("/logout")) { // 로그아웃 처리
			HttpSession session = request.getSession(false);
			session.removeAttribute("auth");
			response.sendRedirect(contextPath + "/board"); 
			return;
		}
		
		else {
			System.out.println("페이지 찾을 수 없음");
			return;
		}
		rd = request.getRequestDispatcher(PREFIX + nextPage + SUFFIX);
		rd.forward(request, response);
	}
}

 

 

- WEB-INF / views / member / joinForm.jsp

 

- joinForm.jsp 생성

기존의 writeForm.jsp 를 복사해서 수정함

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ include file="../layout/header.jsp" %>

<div class="container">
	<div class="text-center jumbotron bg-light">
		<h1>게시글조회</h1>
	</div>
	
	<form action="${contextPath}/board/write" method="post" enctype="multipart/form-data">
		<div class="form-group">
			제목 : <input type="text" class="form-control" name="title">
		</div>
		<div class="form-group">
			내용 : <textarea rows="10" class="form-control" name="content"></textarea>
		</div>
		<div class="form-group">
			작성자 : <input type="text" class="form-control" name="writer" value="${auth.id}" readonly="readonly">
		</div>
		<div class="form-group">
			첨부파일 : <input type="file" class="form-control" name="imageFileName">
		</div>
		<button class="btn btn-primary">등록</button>
	</form>
	<div class="preview"></div>
</div>

<%@ include file="../layout/footer.jsp" %>

 

 

 

- 비밀번호는 노출되면 안되기 때문에 암호화 필요

 

- com.common 패키지 EncryptWrapper 클래스 생성

 

package com.common;

import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

public class EncryptWrapper extends HttpServletRequestWrapper{

	public EncryptWrapper(HttpServletRequest request) {
		super(request);
	}
	
	@Override
	public String getParameter(String key) {
		String value = "";
        if (key != null && key.equals("pwd")) {
            value = getSha512(super.getParameter("pwd"));
        } else {
            value = super.getParameter(key);
        }
		return value;
	}

	private static String getSha512(String pwd) {
        String encPwd = "";
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-512");
            byte[] bytes = pwd.getBytes(Charset.forName("UTF-8"));
            md.update(bytes);
            encPwd = Base64.getEncoder().encodeToString(md.digest());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return encPwd;
    }
	
}

 

- com.common 패키지 EncryptFilter 필터 생성

package com.common;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpFilter;
import javax.servlet.http.HttpServletRequest;

@WebFilter(urlPatterns = {
		"/member/join",
		"/member/login"
})
public class EncryptFilter extends HttpFilter implements Filter {

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		System.out.println("암호필터 동작");
		
		EncryptWrapper ew = new EncryptWrapper((HttpServletRequest)request);
		
		String pwd = request.getParameter("pwd");
		if(request.getParameter("pwd") != null) {
			request.setAttribute("pwd", ew.getParameter("pwd"));
		}
		chain.doFilter(request, response);
	}

}

/member/join 과 /member/login 으로 요청될때 필터에 한번 거치고 가게 함

 

 

- com.domain 패키지 AuthVO 클래스 생성

package com.domain;

import com.domain.MemberVO.MemberGrade;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class AuthVO {
	private String id;
	private MemberGrade grade;
}

 

 
- com.domain 패키지 MemberVO 클래스 생성
package com.domain;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class MemberVO {
	private int mno;
	private String id;
	private String pwd;
	private String name;
	private String email;
}

 

 

- com.dao 패키지 MemberDAO 클래스 생성

package com.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import javax.sql.DataSource;

import com.common.ConnectionUtil;
import com.domain.BoardVO;
import com.domain.MemberVO;

public class MemberDAO {
	
	private DataSource dataSource;
	
	public MemberDAO() {
		dataSource = ConnectionUtil.getDataSource();
	}

	public void insertMember(MemberVO vo) {
		String query = "INSERT INTO t_member(mno, id, pwd, name, email) VALUES(mno_seq.NEXTVAL, ?, ?, ?, ?)";
		try (
			Connection conn = dataSource.getConnection();
			PreparedStatement pstmt = conn.prepareStatement(query);
		){
			pstmt.setString(1, vo.getId());
			pstmt.setString(2, vo.getPwd());
			pstmt.setString(3, vo.getName());
			pstmt.setString(4, vo.getEmail());
			pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// 로그인 체크
	public boolean loingCheck(MemberVO vo) {
		boolean result = false;
		String query = "SELECT DECODE(COUNT(*),1,'TRUE','FALSE') AS RESULT FROM t_member WHERE id=? AND pwd=?";
		
		try (
				Connection conn = dataSource.getConnection();
				PreparedStatement pstmt = conn.prepareStatement(query);
			){
				pstmt.setString(1, vo.getId());
				pstmt.setString(2, vo.getPwd());
				try (ResultSet rs = pstmt.executeQuery();){
					if(rs.next()) {
						result = Boolean.parseBoolean(rs.getString("RESULT"));
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				
				pstmt.executeUpdate();
			} catch (Exception e) {
				e.printStackTrace();
			}
		
		return result;
	}
}

 

 

- com.service 패키지 MemberService 클래스 생성

package com.service;

import com.dao.MemberDAO;
import com.domain.MemberVO;

import lombok.AllArgsConstructor;

@AllArgsConstructor
public class MemberService {
	
	private MemberDAO dao;
	
	// 회원가입
	public void memberJoin(MemberVO vo) {
		dao.insertMember(vo);
	}
	
	public boolean loginService(MemberVO vo) {
		return dao.loingCheck(vo);
	}
}

 

가입하고 데이터에서 확인해보자

암호화된것 확인

 

 

- loginForm.jsp 생성

 

joinForm.jsp를 복사해서 수정함

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ include file="../layout/header.jsp" %>

<div class="container">
	<div class="text-center jumbotron bg-light">
		<h1>로그인</h1>
	</div>
	
	<form action="${contextPath}/member/login" method="post">
		<div class="form-group">
			아이디 : <input type="text" class="form-control" name="id">
		</div>
		<div class="form-group">
			비밀번호 : <input type="password" class="form-control" name="pwd">
		</div>
		<button class="btn btn-primary">로그인</button>
	</form>
</div>

<%@ include file="../layout/footer.jsp" %>

 

 

- controller 패키지 BoardFilter 필터 생성

 

- BoardFilter

package com.controller;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.domain.AuthVO;

@WebFilter(urlPatterns = {
		"/board/writeForm",
		"/board/detail"
})
public class BoardFilter extends HttpFilter implements Filter {

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse reps = (HttpServletResponse) response;
		
		HttpSession session = req.getSession(false);
		AuthVO auth = (AuthVO) session.getAttribute("auth");
		if(auth == null) {
			String userUri = req.getRequestURI();
			String queryString = req.getQueryString();
			userUri += "?" + queryString;
			session.setAttribute("userUri", userUri);
			reps.sendRedirect(req.getContextPath() + "/member/loginForm");
			return;
		}
		
		chain.doFilter(request, response);
	}

}
반응형

댓글