백엔드/쿠키,세션

쿠키,세션

코딩 화이팅 2023. 3. 9. 13:57

HTTP Protocal

  • 비연결(connectionless) 지향형 통신 프로토콜
  • 응답 후 연결을 종료(stateless)
    • 지속적인 연결 유지로 인한 자원낭비 방지를 위해 연결 해제
    • 연결이 해제되면 서버는 클라이언트 정보를 알 수 없음
    • 예) 장바구니에 상품을 담아 두었는데, 페이지가 바뀌면 정보가 없어짐, 로그인 정보가 없음 등 이러한 문제를 해결하기 위해서 Cookie와 HttpSession을 활용한다.

Cookie:javax.servlet.http.Cookie

  • 서버가 생성하는 클라이언트 정보를 가지고 있는 파일
  • 클라이언트 컴퓨터에 저장되며, 필요에 따라 요청 시 서버로 같이 전송된다.
  • key-value 형태로 구성되며 문자열 데이터
  • 브라우저(클라이언트) 별로 별도의 쿠키가 생성된다. (브라우저가 다르면 다른 사용자로 처리)
  • 세션관리(사용자 아이디, 접속시간, 장바구니 등)을 위해 사용된다.
  • 사용자마다 다른 페이지를 보여줄 수 있다.
  • 사용자의 행동과 패턴을 분석하고 기록하는데 사용된다.(사용자가 클릭한 상품 관련 광고 배너)

Cookie 동작순서

  • Client가 요청 생성
  • WAS(Web Application Server)는 Cookie를 생성하고 Http Header에 Cookie를 넣어 응답
  • Client(Browser)는 Cookie를 저장, 해당 서버에 요청할 때 요청과 함께 Cookie를 전송
  • Cookie는 브라우저가 종료되더라도 계속 저장되기 때문에(만료 기간 전까지) 동일 사이트 재방문하여 요청 시 필요에 따라 Cookie가 재전송된다.

Cookie 특징

  • 이름(key), 값(value), 만료일(Expire date,저장기간), 경로정보로 구성된다.
  • 클라이언트에 최대 300개의 쿠키를 저장할 수 있다.
  • 하나의 도메인당 20개의 쿠키를 저장할 수 있다.
  • 쿠키 하나는 4KB(=4096byte)까지 저장 가능

쿠키 생성

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>쿠키</title>
</head>
<body>
	<h2>현재 내 브라우저에 있는 쿠키 정보</h2>
	<hr>
	<%
		Cookie[] cookies = request.getCookies();
// 		request는 jsp가 가지고 있는 기본 객체
// 		getCookies는 request가 가지고 있는 기본 메서드
		if(cookies != null){
// 			쿠키 안에 값이 있다면
			for(Cookie c : cookies){
				String key = c.getName();
// 				getName:키 값을 가져오는 메서드
				String value = c.getValue();
// 				getValue:값을 가져오는 메서드

// 		html코드를 바로 쓰기 위해 잠깐 끊어줄 수 있다.
		%>
				<h3><%=key %>:<%=value %></h3>
		<%
				
			}
		}
		else {
// 			쿠키 안에 값이 없다면
			out.print("설정된 쿠기가 없다.");
		}
	%>



	<h2>쿠키설정</h2>
	<form action="make" method="GET">
		이름 : <input type="text" name="key"><br> 
		값 : <input type="text" name="value" ><br> 
		
		<button>제출</button>
	
	</form>
</body>
</html>
==================================================================
package com.ssafy.cookie;

import java.io.IOException;

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


@WebServlet("/make")
public class MakeCookieServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String key = request.getParameter("key");
		String value = request.getParameter("value");
		
		
		//쿠키를 생성하자.!!!
		Cookie cookie = new Cookie(key, value);
		
		response.addCookie(cookie);
		
		//유효시간(만료시간) 초단위
		cookie.setMaxAge(60); //1분유지하겠다.
		//만료시간을 0으로 한다면 쿠키를 지우는것과 똑같음				
		
		
		response.sendRedirect("01_Cookie.jsp");
		
	}
}

HttpSession

session:javax.servlet.http.HttpSession

  • 사용자가 웹 서버에 접속해 있는 상태를 하나의 단위보고 세션이라고 한다.
  • 각 세션은 sessionid를 이용해 구분한다.
  • WAS의 메모리에 객체 형태로 저장
  • 메모리가 허용하는 용량까지 제한없이 저장 가능
  • 쿠키는 클라이언트에 저장되기 때문에 공유 PC의 경우 보안에 취약할 수 있다. 하지만 세션은 서버에 저장되기 때문에 쿠키에 비해 보안이 좋다.
  • 사용자(로그인 정보)및 장바구니에 활용

session 동작 순서

  • 클라이언트가 페이지를 요청
  • 서버는 쿠키에 session id가 있는지 확인한다.
  • session id가 존재하지 않으면 session id를 생성해 쿠키에 쓴 다음 클라이언트로 반환
  • 생성된 session id를 이용하여 서버 내 메모리를 생성
  • 클라이언트가 다음 요청 시 쿠키에 session id(JSESSIONID)를 포함해 전달하면 서버내에 저장된 session id와 비교하여 데이터를 조회

session 설정

  • 브라우저 당 하나의 JSESSIONID를 할당 받음
  • 아이디 또는 닉네임과 같이 로그인 했을 경우 자주 사용되는 정보를 session에 저장하면 db에 접근할 필요가 없으므로 효율적이다.

session 사용하기

//A.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<%
		pageContext.setAttribute("name", "page yang");
		request.setAttribute("name", "request yang");
		session.setAttribute("name", "session yang");
		application.setAttribute("name", "application yang");
// 		pageContext, request, session, application은 다 jsp의 기본 객체
		
		System.out.println("A.jsp");
		System.out.println("페이지 속성 " + pageContext.getAttribute("name"));
		System.out.println("요청 속성 "+ request.getAttribute("name"));
		System.out.println("세션 속성 "+ session.getAttribute("name"));
		System.out.println("어플리케이션 속성 "+ application.getAttribute("name"));
		
		request.getRequestDispatcher("B.jsp").forward(request, response);
		
	%>
	
	
</body>
</html>
//
A.jsp
페이지 속성 page yang
요청 속성 request yang
세션 속성 session yang
어플리케이션 속성 application yang
==========================================================================
//B.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<p>페이지 속성 : <%= pageContext.getAttribute("name") %></p>
	<p>요청 속성 : <%= request.getAttribute("name") %></p>
	<p>세션 속성 : <%= session.getAttribute("name") %></p>
	<p>애플리케이션속성 속성 : <%= application.getAttribute("name") %></p>
	
	
	<a href="C.jsp">세번째 페이지</a>
</body>
</html>
==========================================================================
//C.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<p>페이지 속성 : <%= pageContext.getAttribute("name") %></p>
	<p>요청 속성 : <%= request.getAttribute("name") %></p>
	<p>세션 속성 : <%= session.getAttribute("name") %></p>
	<p>애플리케이션속성 속성 : <%= application.getAttribute("name") %></p>
</body>
</html>

위 화면은 현재 B.jsp이다.

일단 콘솔창에 print값들을 다 입력 후 requset.getRequestDispatcher로 B로 forward를 한다. forward는 url이 변경되지 않기 때문에 URL은 A.jsp라고 나와있지만 창은 B.jsp이다.

페이지 속성이 null인 이유는 A.jsp안에서만 쓰이기 때문에 B.jsp에서는 페이지 속성이 지워진다.

 

위에서 세번째 페이지를 누르게 되면

새롭게 요청을 보낸거라서 request가 사라진다.

 

이후에 저 브라우저와 모든 브라우저를 끄고 C.jsp에 가서 실행시키면

세션은 브라우저이기 때문에 A.jsp에서 브라우저를 저장했기 때문에 모든 브라우저를 지운 후 C.jsp를 열면 사라진다.

톰캣은 한번도 안 껐기 때문에 애플리케이션 속성은 살아있다. 

 

톰캣을 끄고 실행하면

모두 다 꺼진 걸 확인할 수 있다.

 

만약 다시 서버를 키고 A.jsp를 실행하고

서버를 끄고 다시 킨 후 세번째 페이지를 누르면

아예 다른 서버로 실행시킨 것이기 때문에 모두 다 null이 뜬다. 컴퓨터를 껐다 키면 다시 초기화 되는 거랑 비슷하다고 생각하면 된다.

 

session  만들기

package com.ssafy.session;

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

/**
 * Servlet implementation class SessionServlet
 */
@WebServlet("/hello")
public class SessionServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Override
		protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
			//request가 가지고 있는 세션을 가져오기
			HttpSession session = request.getSession();
						
			session.setAttribute("name", "ssesionYangg");
			
			
//			request.getRequestDispatcher("session/test.jsp").forward(request, response);
			response.sendRedirect("session/test.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>
	<%=session.getAttribute("name") %>
</body>
</html>

세션을 만들고 f12에서 Cookies에 JSESSIONID를 삭제해주고 새로고침을 해주면

sessionYangg이라는 값이 직접 저장이 되는 것이 아니라 JSESSIONID라는 값에 저장이 되는 것이라서 그것을 삭제해주면 sessionYangg이라는 값도 없어진다.

로그인 구현

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인페이지</title>
</head>
<body>
	<h3>로그인페이지</h3>
	<form action="testlogin.jsp" method="POST">
<!-- 	method는 로그인 정보는 주소에 노출될 수 없는 POST를 사용 -->
		<input type="hidden" name="action" value="login">
		<input type="text" placeholder="아이디입력" name="id">
		<input type="password" placeholder="비밀번호입력" name="password">
		<button>로그인</button>
	</form>
</body>
</html>

ssafy/1234를 입력하면 다음 사진으로 넘어가고 다른 값들을 입력한다면 계속 이 페이지로 돌아온다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	String id = request.getParameter("id");
	String pw = request.getParameter("password");
	//loginForm.jsp에 있는 id와 password를 넘겨 받음.
	
	if(id.equals("ssafy") && pw.equals("1234")){
		//로그인성공  (세션에 데이터를 넣자!)
		//세션을 얻어오자.
		
		//HttpSession session = request.getSession();
		//jsp에는 이미 session이라는 객체가 있기 때문에 객체로 생성해주면 안된다.
		
		session.setAttribute("loginUser", id);
// 		id값을 저장
		response.sendRedirect("main.jsp");
//		main.jsp로 보내라
	}else{
		//로그인실패 (다시 로그인 폼으로 보내버려)
		response.sendRedirect("loginForm.jsp");
// 		loginForm.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>
	<%
		if(session.getAttribute("loginUser") == null){
// 			만약 세션값이 아무것도 없다면
			response.sendRedirect("loginForm.jsp");
// 			로그인 화면으로 다시 보내라
		}else{
// 			세션값이 존재한다면
	%>
			<%=session.getAttribute("loginUser")%>님 반갑습니다.
	<%
		}
	%>
	
	<form action="logout.jsp" method="POST">
		<button>로그아웃</button>
	</form>
	<h3>메인페이지 </h3>
</body>
</html>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<!-- 로그아웃을 하는방법으로는 2가지 0 -->
	
	<% session.removeAttribute("loginUser"); %>
		
	<%-- <% session.invalidate(); %> --%>
	
	<script type="text/javascript">
		alert("로그아웃되셨습니다.");
		location.href="loginForm.jsp";
// 		loginForm.jsp로 요청 주소를 바꿔줘라
	</script>
</body>
</html>

확인 버튼을 누르면 다시 로그인 페이지로 넘어간다.