JSP/회원 관리

[JSP] (3) 로그인 - 2

09009 2023. 4. 15. 17:50

로그인 인증 처리

작동원리

아이디, 암호를 입력한 후 <로그인> 버튼을 클릭하면

→ 회원 인증 처리를 하기 위해 서블릿 (LoginServlet)이 요청된다.

→  서블릿에서는 인증 처리에 실패하면 login.jsp로 이동(다시 로그인 작업을 해야하므로), 

                       회원 인증 처리에 성공하면 main.jsp로 이동하도록 한다.

 

! 입력받은 아이디와 암호로 인증 처리를 하려면 데이터베이스에 이러한 회원 정보가 존재하는지 확인 해야 한다.

위의 작업을 수행하기 위해 아래 메서드를 DAO 클래스에 추가해야 한다.

userCheck() member 테이블에서 아이디, 암호를 비교하여 해당 아이디가 존재하지 않을 경우 -1, 
아이디만 일치하고 암호가 다르면 0, 모두 일치하면 1 반환
getMember() member 테이블에서 아이디로 해당 회원을 찾아 회원 정보를 MemberVO 객체로 가져온다

 

member 테이블 

 


 

회원 인증을 위한 메서드 추가

✍ MemberDAO.java

package dao;

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

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;

import dto.MemberVO;

public class MemberDAO {
	private MemberDAO() {
		
	}
	private static MemberDAO instance = new MemberDAO();
	
	public static MemberDAO getInstance() {
		return instance;
	}
	
	public Connection getConnection() throws Exception {
		Connection conn = null;
		Context initContext = new InitialContext();
		Context envContext = (Context) initContext.lookup("java:/comp/env");
		DataSource ds = (DataSource) envContext.lookup("jdbc/myoracle");
		conn = ds.getConnection();
		return conn;
	}
	
	// 사용자 인증시 사용하는 메서드
	public int userCheck(String userid, String pwd) {
		int result = -1;
		String sql = "select pwd from member where userid=?";
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		try {
			conn = getConnection();
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1,  userid);
			rs = pstmt.executeQuery();
			
			if (rs.next()) {
				if (rs.getString("pwd") != null && rs.getString("pwd").equals(pwd)) { 
					// 아이디와 암호가 모두 일치하는 경우
					result = 1;
				} else {
					// 아이디만 일치하고 암호가 다른 경우
					result = 0;
				}
			} else {
				result = -1; // 해당 아이디가 존재하지 않을 경우
			}	
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (rs != null) rs.close();
				if (pstmt != null) pstmt.close();
				if (conn != null) conn.close();
			}catch(Exception e) {
				e.printStackTrace();
			} 
		}
		return result;
	}
	
	// 아이디로 회원 정보 가져오는 메서드
	public MemberVO getMember(String userid) {
		MemberVO mvo = null;
		String sql = "select * from member where userid=?";
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		try {
			conn = getConnection();
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1,  userid);
			rs = pstmt.executeQuery();
			
			if (rs.next()) {
				mvo = new MemberVO();
				mvo.setName(rs.getString("name"));
				mvo.setUserid(rs.getString("userid"));
				mvo.setPwd(rs.getString("pwd"));
				mvo.setEmail(rs.getString("email"));
				mvo.setPhone(rs.getString("phone"));
				mvo.setAdmin(rs.getInt("admin"));
		} 
		}catch(Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (rs != null) rs.close();
				if (pstmt != null) pstmt.close();
				if (conn != null) conn.close();
			}catch(Exception e) {
				e.printStackTrace();
			} 
		}
		return mvo;
	}
 }

login.do는 get 방식으로 요청되었는지 post 방식으로 요청되었는지에 따라 처리 방법이 달라진다.

get 방식 : 로그인, 회원 가입이나 게시글 작성과 같은 입력 폼이 화면에 나타나도록 해야할 때 요청한다.

post 방식:  로그인 정보와 회원 정보, 게시글 정보를 모두 입력한 후, 데이터베이스에 정보를 저장하기 위한 작업

                     해야할 때 요청한다.

 

지난 게시물에서 index.jsp 페이지에서 [로그인 페이지로 이동]을 클릭하였을 때 로그인 페이지가 나타난 것을 확인하였다.

                 [로그인 페이지로 이동]을 클릭한 후                                     

                                                 ↓

index.jsp 페이지에서 [로그인 페이지로 이동]을 클릭하면 로그인 페이지가 나타나도록 하기 위해 

index.jsp에 위와 같이 코드를 작성하였고

get 방식으로 요청하였을 때 로그인 입력 폼이 나타날 수 있도록 (login.jsp로 이동할 수 있도록) 서블릿을 아래와 같이 정의하였다.

 

이번에는 아이디와 암호를 입력한 후 <로그인> 버튼을 클릭하면 입력된 정보를 받아서

데이터베이스에 해당 정보가 저장되어 있는지 확인하는 작업을 살펴보고자 한다.

 

위 작업도 서블릿에서 진행해야 하는데 요청 방식만 post로 주어서 로그인을 위한 데이터베이스 처리 작업을 할 것이다.

<form> 태그의 action 속성에 login.do를 기술하고 method 속성에 post를 지정한다.

<form action="login.do" method="post" name="frm">

로그인 인증을 위한 데이터베이스 처리 작업을 위해 login.do는 post 방식으로 요청되어야 한다.

→ 서블릿에 doPost()를 아래와 같이 작성한다.

 

✍ LoginServlet.java

package controller;

import java.io.IOException;

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 javax.servlet.http.HttpSession;

import dao.MemberDAO;
import dto.MemberVO;

@WebServlet("/login.do")
public class LoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		RequestDispatcher dispatcher = request.getRequestDispatcher("member/login.jsp");
		dispatcher.forward(request, response);
	}


	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String url = "member/login.jsp"; 
		
		String userid = request.getParameter("userid");
		String pwd = request.getParameter("pwd");
		
		MemberDAO mdao = MemberDAO.getInstance();
		int result = mdao.userCheck(userid, pwd);
		
		if (result == 1) {  
			MemberVO mvo = mdao.getMember(userid);
			HttpSession session = request.getSession();
			session.setAttribute("loginUser", mvo);
			request.setAttribute("message", "로그인에 성공하였습니다.");
			url = "main.jsp"; // 로그인에 성공할 경우 main 페이지로 이동하기 위함
		} else if (result == 0) { 
			request.setAttribute("message","비밀번호가 일치하지 않습니다.");
		} else if (result == -1) {
			request.setAttribute("message","회원가입이 되어 있지 않습니다.");
		}
		
		RequestDispatcher dispatcher = request.getRequestDispatcher(url);
		dispatcher.forward(request, response);
	}

}

세션 객체에 대해 아무것도 수정하지 않은 상태일 때, 로그인 정보 세션은  30분 유지되도록 설정되어 있다.

servers/Tomcat9.0/web.xml에 설정된 세션

 

코드 설명

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 회원 인증이 실패할 경우 이동할 login.jsp 페이지를 url 변수에 저장
		String url = "member/login.jsp"; 
		
		// login.jsp 로그인 폼에서 입력한 아이디, 암호를 얻어와 변수에 저장
		String userid = request.getParameter("userid");
		String pwd = request.getParameter("pwd");
		
		// 입력받은 아이디와 암호로 회원 인증 여부를 확인하기 위해 
		// 회원 가입 시 회원 정보를 member 테이블에 저장해두었기 때문에
		// member 테이블에 존재하는 아이디인지 확인해야 한다.
		// MemberDAO의 userCheck() 메서드에서 아이디에 해당되는 회원이 존재하는지 조회한다.
		// 위 메서드를 호출하여 데이터베이스에 등록된 회원인지 검사하여 결과값을 얻어온다.
		MemberDAO mdao = MemberDAO.getInstance();
		int result = mdao.userCheck(userid, pwd);
		
		if (result == 1) { // 아이디가 DB에 존재하고 비밀번호를 올바르게 입력했을 때
			// 회원 인증에 성공하였으므로 회원 정보를 얻어온다.
			MemberVO mvo = mdao.getMember(userid);
			// 로그인 인증 처리된 정보는 다른 사이트에 갔다 돌아와도 
			// 다시 로그인하지 않도록 하기위해 세션에 등록해 둔다.
			// 세션 객체를 생성하여 세션에 회원 정보를 저장한다.
			HttpSession session = request.getSession();

			session.setAttribute("loginUser", mvo);
			request.setAttribute("message", "로그인에 성공하였습니다.");
			url = "main.jsp"; // 로그인에 성공할 경우 main 페이지로 이동하기 위함
		} else if (result == 0) { 
			request.setAttribute("message","비밀번호가 일치하지 않습니다.");
		} else if (result == -1) {
			request.setAttribute("message","회원가입이 되어 있지 않습니다.");
		}
		
		RequestDispatcher dispatcher = request.getRequestDispatcher(url);
		dispatcher.forward(request, response);
	}

}

회원 인증된 사용자에게 제공되는 메인 페이지 생성

회원 인증된 사용자에게 제공되는 메인 페이지 (main.jsp로 작성할 예정)는 회원과 관련된 내용이 아니므로

member 폴더에 생성하지 않고 webapp 폴더 바로 아래에 생성한다.

프로젝트에 오른쪽 마우스를 클릭하고 [New - JSP File]을 클릭하면 아래 폴더에 main.jsp가 생성된다.

 

✍ main.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri = "http://java.sun.com/jsp/jstl/core" prefix="c" %> 
<c:if test="${empty loginUser}">
	<jsp:forward page='login.do' />
</c:if>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 관리</title>
<script type="text/javascript" src="script/member.js"></script>
</head>
<body>
<h2>회원 전용 페이지</h2>
<form action="logout.do">
 <table>
  <tr>
   <td>
   안녕하세요. ${loginUser.name}(${loginUser.userid})님!
   </td>
  </tr>
  <tr>
  	<td>${message}</td>
  <tr>
   <td colspan="2" align="center">
   <input type="submit" value="로그아웃"> &nbsp;&nbsp;
   <input type="button" value="회원정보변경"
	 onclick="location.href='memberUpdate.do?userid=${loginUser.userid}'">
   </td>
  </tr>
 </table>
</form>
</body>
</html>

코드 설명

<%@ taglib uri = "http://java.sun.com/jsp/jstl/core" prefix="c" %>

JSTL 태그 라이브러리를 사용하기 위한 지시자이다.

JSTL 태그 라이브러리는 standard.jar와 jstl.jar에서 제공되므로 이를 사용하려면 lib 폴더에 두 파일을 복사하여야 한다.

<로그아웃> 버튼을 클릭하면 logout.do가 요청되어 이 요청을 받는 서블릿에서 logout.jsp로 이동시킬 것이다.

logout.jsp에서는 인증된 사용자의 인증을 무효화한다. logout.jsp 파일은 아직 작성되지 않았고

추후 문서에서 작성할 계획이다.

 

<회원정보변경> 버튼을 클릭하면 회원 정보 수정 페이지로 이동하도록 설계한다.

이전에 입력된 회원 정보를 보여줘야 하므로 memberUpdate.do 요청 시 사용자의 아이디를 파라미터로 전달한다.


정리

지금까지 아래와 같은 파일을 작성하였다.

 

[회원 정보에 관한 페이지]

파일 설명
MemberVO.java 원 테이블의 정보를 자바에서 얻어와 저장할 공간을 만들 목적으로 만든 클래스
MemberDAO.java 데이터베이스 member 테이블과 연동해서 작업하는 회원 테이블에서
 
정보를 조회,추가,수정,삭제 작업을 위한 목적으로 만든 클래스

 

[JSP 페이지] 

파일 설명
login.jsp 아이디와 비밀번호를 입력받는 폼 (회원 인증을 하기 위함)
main.jsp 회원 인증 후 회원 전용 페이지로 이동하여 다양한 서비스를 제공하기 위한 폼
index.jsp login.jsp로 이동하기 위한 홈페이지 (프론트 페이지)

 

[서블릿 파일] 

파일 설명 URL pattern
loginServlet.java 회원 인증 처리 (아이디, 비밀번호 입력 처리) login.do

 

[자바스크립트 파일] 

파일 설명
member.js 폼에 입력된 정보가 올바른지 판단

 

 

작업 순서

1) index.jsp 페이지에서 get 방식으로 login.do를 요청하면

2) LoginServlet의 doGet() 메서드가 호출되어 login.jsp 페이지로 이동(포워딩)한다.

3) 로그인 페이지(login.jsp)에서 아이디와 암호를 입력한 후 <로그인> 버튼을 클릭하면

4) post 방식으로 login.do를 요청한다.

5) 이후, LoginServlet의 doPost() 메서드가 호출되어 회원인지 검사한 후 

6) 회원 정보를 세션에 저장하고 메인 페이지(main.jsp)로 이동한다.