본문 바로가기
Java Web Programming/4. JSP

[JSP/세션관리] 1단계_Cookie 쿠키 & Session 세션을 이용한 로그인 유지 프로그램 구현

by 파프리카_ 2020. 9. 1.
728x90
반응형

[ 진행 과정(흐름) ]

출처 : https://velog.io/@junhok82/%EB%A1%9C%EA%B7%B8%EC%9D%B8%EC%9D%80-%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%9D%B4%EB%A3%A8%EC%96%B4%EC%A7%88%EA%B9%8CCookie-Session


                                                                                         WAS (Web Container)

client(browser) ---> request ----->  if (모델과 연동해 아이디 패스워드 일치하면)

                                                                       HttpSession session = request.getSession( );

                                                                       : 위 코드는 세션이 없으면 새로 생성, 있으면 기존 세션 리턴

                                                                       session.setAttribute(name, value) ;
                                                                       : 위 코드는 로그인 인증 정보(주로 회원 객체)를 주로 할당

                                                                       WAS 상에서는 클라이언트에 대응하는 세션 객체가 생성되어 있고,

                                                                       클라이언트에게 응답할 때 생성된 세션 객체의 고유 아이디를 쿠키로 전달

                                     <-- response  --   reponse : 즉, 응답 시에 클라이언트에게 쿠키 전달 (쿠키 심기)

cookie가 저장

 

client(browser) ---> request -----> if ( 로그인 시 발급한 세션 아이디가 기록된 쿠키 정보가 있는지 확인 )

                                                                     HttpSession session = request.getSession(false);

                                                                    : 위 코드는 기존 세션이 있으면 -> 기존 세션을 반환 / 없으면 -> null 을 반환

                                                                    로그인한 사용자인지  여부 확인은 위와 같이 세션이 있는지와  

                                                                    + 로그인 처리 시 할당한 인증정보가 있는지를 함께 확인한다.

                                                                      

                                                                    즉, 로그인한 사용자인지 확인하는 방법은

                                                                   세션이 존재 && 로그인 시 할당한 attribute의 존재

                                                                    를 확인하고 인증정보가 있으면 로그인 되어있다고 처리하면 된다.

 


[ 전체 구현 코드 ] 

DB Table

 

Model

/MemberVO.java

package org.kosta.model;

public class MemberVO {
	private String id;
	private String password;
	private String name;
	private String address;
	
	@Override
	public String toString() {
		return "MemberVO [id=" + id + ", password=" + password 
				+ ", name=" + name + ", adress=" + address + "]";
	}
	
	public MemberVO() {
		super();
	}

	public MemberVO(String id, String password) {
		super();
		this.id = id;
		this.password = password;
	}

	public MemberVO(String id, String password, String name, String address) {
		this.id = id;
		this.password = password;
		this.name = name;
		this.address = address;
	}


	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

}

 

/ProductDAO.java

package org.kosta.model;

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

public class MemberDAO {
	//singleton 적용
	private static MemberDAO instance = new MemberDAO();
	
	//JDBC에 필요한 변수
	private String driver = "oracle.jdbc.OracleDriver";
	private String url = "jdbc:oracle:thin:@127.0.0.1:1521:xe";
	private String username = "scott";
	private String userpass = "tiger";

	//class 생성 단계에서 singleton으로 한번 생성 + driver loading
	//사실 driver loading은 현재 java version에서는 따로 기재해주지 않아도,
	//자동으로 loading된다 ! 
	private MemberDAO() {
		try {
			Class.forName(driver);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	//getInstance() method : 생성자 객체 반환용
	public static MemberDAO getInstance() {
		return instance;
	}
	
	//closeAll method 1
	public void closeAll(PreparedStatement pstmt, Connection con) 
			throws SQLException {
		if (pstmt != null)
			pstmt.close();
		if (con != null)
			con.close();
	}
	
	//closeAll method 2
	public void closeAll(ResultSet rs, PreparedStatement pstmt, Connection con) 
			throws SQLException {
		if (rs != null)
			rs.close();
		//재사용
		this.closeAll(pstmt, con);
	}
	
	/*
	 * 1번 기능 : 아이디로 회원정보 조회
	 * findMemberById(String):MemberVO 
	 */
	public MemberVO findMemberById(String id) throws SQLException {
		MemberVO vo = null;
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		try {
			con = DriverManager.getConnection(url, username, userpass);
			String sql = "SELECT name, address FROM web_member " 
					+ "WHERE id = ?";
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, id);
			rs = pstmt.executeQuery();
			if(rs.next()) {
				vo = new MemberVO(id, null, rs.getString(1),rs.getString(2));
			}
			
		} finally {
			closeAll(rs, pstmt, con);
		}
		
		return vo;
	}
	
	/*
	 * 2번 기능 : 로그인 기능
	 * login(MemberVO):MemberVO 
	 */
	public MemberVO login(MemberVO vo) throws SQLException {
		MemberVO mvo = null;
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		try {
			con = DriverManager.getConnection(url, username, userpass);
			String sql = "SELECT name, address FROM web_member "
					+ "WHERE id=? AND password=?";
			pstmt = con.prepareStatement(sql);
			
			pstmt.setString(1, vo.getId());
			pstmt.setString(2, vo.getPassword());
			
			rs = pstmt.executeQuery();
			
			if(rs.next()){
				mvo = new MemberVO(vo.getId(), null,
						rs.getString("name"),rs.getString("address"));
			}
		} finally {
			closeAll(rs, pstmt, con);
		}
		return mvo;
	}
	
}//class

View

/index.jsp

<%@page import="org.kosta.model.MemberVO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8" session="false"%>
<!DOCTYPE html>
<html>
<link rel="stylesheet" type="text/css" href="css/mystyle.css">
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
	<div class="container">
		<h4>
			<a href="index.jsp"><img class="home-image" src="home.png">Home</a>
		</h4>
		<hr>
		<h3>Model2 회원 관리</h3>
		<a href="findmemberbyid.jsp">회원 검색</a><br>
		<%
			//로그인 여부 확인 방법 
			//(session 유무 확인 + 로그인 시 할당한 attribute 존재 확인)
			
			HttpSession session = request.getSession(false);
			if (session != null && session.getAttribute("mvo") != null) {
				MemberVO mvo = (MemberVO) session.getAttribute("mvo");%>
				<br><%=mvo.getAddress() %>에 사는 <%=mvo.getName() %>님 로그인 상태<br>
				<a href="front?command=logout">로그아웃</a>
		<%
			} else {
		%>
			<a href="login.jsp">로그인 페이지로</a>
		<%	
			}
		%>
	</div>
</body>
</html>

 

/error.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>예외 페이지</title>
</head>
<body>
	<marquee>
		시스템 에러가 발생했습니다. 콘솔을 확인하세요!<br>
		<br> <img src="error.jpg">
	</marquee>
</body>
</html>

 

-- 1번 기능 : 아이디를 입력하여 회원 정보 검색

FindMemberByIdController      <----->     MemberDAO

                                                                                findMemberById(String id) : MemberVO

                        ㅣ forward

       findmemberbyid-ok.jsp

       아이디와 이름, 주소를 제공한다.

                          or

       findmemberbyid-fail.jsp

       javascript alert : [    ] 에 해당하는 회원이 없습니다.

       location.href로 index.jsp로 이동한다.

 

/findmemberbyid.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8" session="false"%>
<!DOCTYPE html>
<html>
<link rel="stylesheet" type="text/css" href="css/mystyle.css">
<head>
<meta charset="UTF-8">
<title>회원 검색 Form</title>
</head>
<body>
	<div class="container">
		<a href="index.jsp">Home</a>
		<hr>
		<form action="front" method="get">
			<input type="hidden" name="command" value="findmemberbyid">
			아이디 <input type="text" name="id" required="required">
			<input type="submit" value="회원 검색">
		</form>
	</div>
</body>
</html>

 

/findmemberbyid-ok.jsp

<%@page import="org.kosta.model.MemberVO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8" session="false"%>
<!DOCTYPE html>
<html>
<link rel="stylesheet" type="text/css" href="css/mystyle.css">
<head>
<meta charset="UTF-8">
<title>회원 상세 정보</title>
</head>
<body>
	<%
		MemberVO vo = (MemberVO) request.getAttribute("vo");
	%>
	<%=vo.getId()%>님의 회원 정보입니다.<br>
	<br>
	<table>
		<tr>
			<td>ID</td>
			<td><%=vo.getId()%></td>
		</tr>
		<tr>
			<td>NAME</td>
			<td><%=vo.getName()%></td>
		</tr>
		<tr>
			<td>ADDRESS</td>
			<td><%=vo.getAddress()%></td>
		</tr>
	</table>
</body>
</html>

 

/findmemberbyid-fail.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" session="false"%>
<!DOCTYPE html>
<html>
<link rel="stylesheet" type="text/css" href="css/mystyle.css">
<head>
<meta charset="UTF-8">
<title>오류 페이지</title>
</head>
<body>
	<script type="text/javascript">
		alert("<%=request.getParameter("id") %>에 해당하는 회원이 없습니다.");
		location.href = "index.jsp";
	</script>
</body>
</html>

 

-- 2 + 3번 기능 :  로그인 + 로그아웃 기능

                                                                                                                   

login.jsp -- command=login -->  LoginController      <----->    MemberController

                                                                                ㅣ                                     login(MemberVO)

                                                                                ㅣ

                                                                    ㅣ                  ㅣ

                                                  login-fail.jsp           login-ok.jsp

                                        로그인 실패! alert 후        [name] 님 로그인하셨습니다.

                                        index.jsp로 이동               만약 상단부에 Home 링크를 클릭하면

                                                                                       index.jsp 에서는 

                                                                                       login.jsp 으로

                                                                                         -> 링크는 보여주지 않고,

                                                                                      [address]에 사는 [name]님 로그인 상태  + 로그아웃 링크 를 보여준다.

                                                                                       로그아웃 링크를 누르면,

                                                                                      LogoutController가 동작되고,

                                                                                      로그아웃 처리 후,  index.jsp로 redirect한다.

                                                                                      로그아웃 처리된 index.jsp는 '다시 로그인 폼으로'라는 링크가 제공된다.

                               

/login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" session="false"%>
<!DOCTYPE html>
<html>
<link rel="stylesheet" type="text/css" href="css/mystyle.css">
<head>
<meta charset="UTF-8">
<title>로그인 form</title>
</head>
<body>
	<div class="container">
		<a href="index.jsp"><img class="home-image" src="home.png">Home</a>
		<hr>
		<form action="front" method="POST">
			<input type="hidden" name="command" value="login">
			아이디 <input type="text" name="id" required="required"><br>
			패스워드 <input type="password" name="password" required="required"><br>
			<input type="submit" value="로그인">
		</form>
	</div>
</body>
</html>

 

/login-ok.jsp

<%@page import="org.kosta.model.MemberVO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8" session="false"%>
<!DOCTYPE html>
<html>
<link rel="stylesheet" type="text/css" href="css/mystyle.css">
<head>
<meta charset="UTF-8">
<title>로그인 성공</title>
</head>
<body>
	<div class="container">
		<a href="index.jsp"><img class="home-image" src="home.png">Home</a>
		<hr>
		<%
			HttpSession session = request.getSession(false);
			
			//로그인 여부 확인 방법
			
			//1단계. 세션이 존재하는지
			//session이 null이 아니면(session이 있으면)
			if (session !=null) {
				//session에서 mvo값 가져오기
				MemberVO mvo = (MemberVO) session.getAttribute("mvo");
				
				// 2단계. 로그인 시 할당한 attribute가 존재하는지
				//mvo도 null이 아니면
				if (mvo !=null) {  %>
					<h4>
						<%=mvo.getName()%>님, 로그인 성공했습니다!
					</h4>
				<% } %>
		<% } else { %>
			<a href="login-fail.jsp">로그인 실패</a>
		<% } %>
	</div>
</body>
</html>

 

/login-fail.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8" session="false"%>
<!DOCTYPE html>
<html>
<link rel="stylesheet" type="text/css" href="css/mystyle.css">
<head>
<meta charset="UTF-8">
<title>로그인 실패</title>
</head>
<body>
	<div class="container">
		<a href="index.jsp"><img class="home-image" src="home.png">Home</a>
		<hr>
		<script type="text/javascript">
			alert("로그인 실패!");
			location.href = "index.jsp";
		</script>
	</div>
</body>
</html>

Controller

/DispatcherServlet.java

package org.kosta.controller;

import java.io.IOException;

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

/*
 * Front Controller Design Pattern이 적용되었음!
 * -> 모든 클라이언트의 요청을 한 곳(front)으로 집중시켜,
 *    일관성 있는 정책을 이용
 */
@WebServlet("/front")
public class DispatcherServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
	protected void doGet(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
		handleRequest(request, response);
	}
	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
		//POST 방식 한글 처리
		request.setCharacterEncoding("utf-8");
		handleRequest(request, response);
	}
	
	/* handleRequest method()
	 * 1. 모든 예외는 error.jsp로 응답한다.
	 * 2. 클라이언트가 전송한 command를 return 받아 온다.
	 * 3. HanlerMapping에게 command를 전달하여 개발 컨드롤러 객체를 리턴 받는다.
	 * 4. 개별 Controller 객체를 실행시킨다.
	 * 5. 실행 후 return 값에 의해 forward와 redirect방식으로 각각 응답한다.
	 */
	public void handleRequest(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
		
		try {
			//2. 클라이언트가 전송한 command를 return 받아 온다.
			String command = request.getParameter("command");
			
			//3. HanlerMapping에게 command를 전달하여 개발 컨드롤러 객체를 리턴 받는다.
			Controller controller = HandlerMapping.getInstance().create(command);
			
			//4. 개별 Controller 객체를 실행시킨다.
			String url = controller.execute(request, response).trim();
			
			//5. 실행 후 return 값에 의해 forward와 redirect방식으로 각각 응답한다.
			if (url.startsWith("redirect:"))
				response.sendRedirect(url.substring(9));
			else
				request.getRequestDispatcher(url).forward(request, response);
			
		} catch (Exception e) {
			// 에러 메세지 콘솔에서 확인
			e.printStackTrace();
			// 1. 모든 예외는 error.jsp로 응답한다.
			response.sendRedirect("error.jsp");
		}
	}
}

 

/ HandlerMapping.java

package org.kosta.controller;
/*
 * 개별 컨트롤러 객체 생성을 전담하는 팩토리 클래스
 */
public class HandlerMapping {
	// singleton pattern으로 객체 생성
	private static HandlerMapping instance = new HandlerMapping();
	private HandlerMapping() { }
	public static HandlerMapping getInstance() {
		return instance;
	}
	
	/* create method() 생성
	 * command에 따라 개별의 Controller를 만들어주는 기능
	 */
	public Controller create(String command) {
		Controller controller = null;
		
		if(command.contentEquals("findmemberbyid"))
			controller = new FindMemberByIdController();
		else if(command.contentEquals("login"))
			controller = new LoginController();
		else if(command.contentEquals("logout"))
			controller = new LogoutController();
		return controller;
	}
}

 

/controller.java

package org.kosta.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public interface Controller {
	
	//execute 메서드 생성
	public String execute(HttpServletRequest request, HttpServletResponse response) 
			throws Exception;
}

-- 1번 기능 : 아이디를 입력하여 회원 정보 검색 기능 controller

/FindMemberByIdController.java

package org.kosta.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.kosta.model.MemberDAO;
import org.kosta.model.MemberVO;

public class FindMemberByIdController implements Controller {

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		//반환할 url 주소
		String url = null;
		
		//View에서 입력값 받아오기
		String id = request.getParameter("id");
		
		//Model(MemberDAO)과 연동
		MemberVO vo = MemberDAO.getInstance().findMemberById(id);
		
		//연동 결과에 따라 View 화면 이동할 url 제공
		if (vo == null) { //아이디에 해당하는 값이 없으면
			url = "findmemberbyid-fail.jsp";
		} else { //아이디에 해당하는 값이 있으면
			url = "findmemberbyid-ok.jsp";
			//View에 연동 결과 공유
			request.setAttribute("vo", vo);
		}
		
		return url;
	}

}

 

-- 2번 기능 : 로그인 기능 controller

/LoginController.java

package org.kosta.controller;

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

import org.kosta.model.MemberDAO;
import org.kosta.model.MemberVO;

public class LoginController implements Controller {

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		
		//반환할 url 주소
		String url = null;
		
		//JSP에서 입력값 받아오기
		String id = request.getParameter("id");
		String password = request.getParameter("password");
		
		//Model과 연동
		//vo : 입력받은 값으로 만든 MemebrVO 객체
		MemberVO vo = new MemberVO(id, password);
		//mvo : model과 연동하여 vo를 넣어 결과값으로 받은 MemberVO 객체
		MemberVO mvo = MemberDAO.getInstance().login(vo);
				
		//View로 이동 : redirect방식으로 
		if (mvo == null) { //로그인 실패
			url = "redirect:login-fail.jsp";
		} else { //로그인 성공
			url = "redirect:login-ok.jsp";
			//세션 생성
			HttpSession session = request.getSession();
			//세션에 정보(mvo) 할당 - View에 정보 공유
			session.setAttribute("mvo", mvo);
		}
		
		return url;	
	}

}

 HttpSession session = requeset.getSession() 
→ 세션 생성 이유 : HTTP 는 Stateless(상태 정보 유지 X)하기 때문에, 로그인 (클라이언트) 상태 정보를 유지하기 위해서다!

session.setAttribute( ) 

→  세션에 정보 할당 이유 : 세션에 클라이언트의 상세 정보를 담아서 View에 보내주기 위함이다!

 

 

-- 3번 기능 : 로그아웃 기능 controller

/LogoutController.java

package org.kosta.controller;

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

public class LogoutController implements Controller {

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response) 
			throws Exception {
		
		HttpSession session = request.getSession(false);
		
		//로그인 정보가 있으면 세션정보 초기화
		if (session != null)
			session.invalidate();
		
		return "redirect:index.jsp";
	}

}

 

브라우저 결과 화면

 

 

728x90
반응형