대덕공부/Spring

기본객체 - Session

02O2 2022. 6. 17. 21:04

>> 더이상 이걸 사용하지않겟다 어플리케이션을 떠날때를 한 세션이라고 지정

>> 그기간안에 사용한 여러가지 객체가 세션

>> 예) 로그인

>> 세션타임아웃은 마지막요청과 새로운요청사이의 시간. 이 타임 지나면 세션이 끊긴다.

>> 세션시간이 길어지면 길어질수록  공격이 받기가 쉽다.

 

 

session 객체는 클라이언트와 서버와의 관계를 유지해주는 수단입니다. 그냥 세션(Session)이라는 용어는 '연결된 상태'라는 의미입니다. 채팅 프로그램을 만들 때처럼 일반적으로 자바를 이용해 클라이언트-서버 간 프로그램을 작성할 때는 소켓을 이용해 통신을 연결합니다. 이 경우 서버의 서버소켓과 클라이언트의 소켓이 연결된 상태를 세션이 맺어졌다고 표현합니다. 그리고 클라이언트 또는 서버에서 해당 연결을 끊지 않는 한 세션이 계속 맺어진 상태로 있으며 세션이 끊길 경우 통신이 종료되고 다시 연결하기 위해서는 프로그램을 재구동 해서 다시 세션을 맺어줘야 합니다.

 

하지만 HTTP 프로토콜은 계속 세션을 맺은 상태로 클라이언트와 서버가 연결돼 있는 것이 아니라 클라이언트가 서버에 요청을 할 때 세션이 맺어지고 서버에서 클라이언트로 응답을 보낸 이후 세션이 끊깁니다. 서버 입장에서는 요청에 따른 응답을 하고 나면 클라이언트와의 연결이 끊어지므로 더 이상 클라이언트에 대해 신경쓰지 않게 됩니다.

 

하지만 이렇게 세션이 매번 끊어져버린다면, 예를 들어 웹 사이트에서 클라이언트가 로그인을 요청하고 서버가 해당 계정을 확인한 뒤 로그인이 완료된 다음 페이지를 보여주더라도 계속해서 클라이언트가 로그인된 상태를 유지하기 어렵게 됩니다. 따라서 세션이 끊어지더라도 지속적으로 서버측에서 클라이언트에 대한 접속 정보를 가지고 있음으로써 로그인을 유지할 수 있게 해주는 객체가 바로 JSP의 내장객체이자 자바의 HttpSession 객체인 session 입니다로그인 뿐만 아니라 지속적인 관계를 유지해야하는 서비스에서 session 객체를 활용할 수 있습니다. 

한번생성이되고 그뒤 에 세션이 소멸될때까지 유지

 

* 쿠키(Cookie)와 세션(Session)의 차이점

>>세션의 대상은 한명의 클라이언트 한명의 브라우저,  쿠키저장소는 브라우저마다 각기 따로 따로 저장 

>>엣지쿠키를 크롬이 건드릴수없음~ 세션의 대상은 사람이아니라 에이전트가 된다

ssl 오고가는 데이터를 암호화하는 방식

 

쿠키는 서버가 보내준 특정한 정보를 클라이언트(브라우저) 측에서 가지고 있는 방식입니다. 로그인의 예를 들면 로그인을 통과했을 경우에만 특정 정보값과 계정정보를 클라이언트측에 저장하게 하고 로그인 된 이후의 페이지에 대한 요청이 올 때는 클라이언트의 쿠키 정보에 로그인을 통과한 정보가 있는지를 판단하고 계정정보를 가져와 해당 계정에 관한 정보를 출력해주는 방식으로 사용할 수 있습니다. 하지만 클라이언트측에서 인증 정보를 가지고 있는 경우는 보안이 취약하다는 단점이 있습니다. 해당 정보를 조작해서 서버의 인증을 우회하는 방식 등이 사용됩니다. 

 

하지만 세션의 경우는 서버에서 클라이언트에 대한 정보를 가지고 있다는 점에서 쿠키와 다릅니다. 서버에서 정보를 관리함으로써 쿠키에 비해 보안을 향상시킨 방법입니다. 따라서 로그인 인증과 같은 민감한 정보에 대해서는 쿠키보다 세션 방식을 사용하는 것이 좋습니다. 또한 쿠키는 저장할 수 있는 데이터의 한계가 있는 반면 세션은 서버에 저장되는 정보이기 때문에 저장할 수 있는 데이터의 한계가 없다는 장점도 있습니다.

 

쿠키 관련해서는 아래 링크글을 참조하시면 됩니다.

 

2020/02/18 - [· JSP & Servlet/- 기본 문법] - 쿠키(Cookie)

 

 


 

 

세션 객체컨테이너에서 자동으로 생성해줍니다. 세션의 단위는 브라우저입니다. 같은 PC에서도 다른 브라우저로 접속하면 다른 사용자로 인식합니다. 크롬에서 로그인하고 익스플로러도 다시 켜보면 로그인이 안돼있는 것이 이 때문입니다. 또 브라우저가 완전히 다 닫히고 다시 열리게 되도 식별자가 달라서 다른 세션으로 인식합니다. 하지만 브라우저가 완전히 닫히지 않은 상태에서 창을 하나 더 열 때는 같은 브라우저로 인식합니다 .예를 들어 크롬창을 두 개 열어서 한쪽에서 로그인을 하고 다시 껐다 키더라도 다른 하나의 창을 끄지 않았기 때문에 같은 브라우저로 인식해 session 객체를 새로 생성하지 않습니다. 같은 브라우저를 여러 개 키고 하나의 브라우저로 로그인을 했을 때 다른 브라우저에서도 로그인이 돼 있는 것은 이 때문입니다.

 

세션 정보는 계속 유지해줄 수도 있지만 대부분 권고되는 보안 규정에 따라 30~60분 사이로 세션이 유지되는 최대 시간을 조절해 주는 경우가 많습니다. 디폴트는 대부분 30분으로 web.xml에 <session-timeout> 태그에 기술되어 있습니다. 이 부분에서 시간을 조정해주거나 메소드를 통해 재조정해줄 수도 있습니다. 

    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>

 

 

session 주요 메소드 설명
void setAttribute(String name, Object value) 파라미터 이름에 따른 객체를 추가
Object getAttribute(String name) 파라미터 이름에 따른 객체를 반환
void removeAttribute(String name) 파라미터 이름에 따른 객체를 삭제
void invalidate() 세션의 모든 삭제를 삭제 (세션 무효화)
Enumeration<String> getAttributeNames() 등록된 모든 파라미터 이름을 반환
String getID() 해당 세션(브라우저)의 고유 식별자 정보 반환
Boolean isNew() 세션 객체가 최초로 생성되었는지 여부 반환
void setMaxInactiveInterval(int interval) 세션이 유지되는 유효시간을 설정
int getMaxInactiveInterval() 세션에 설정된 유효시간을 반환

 

 

컨테이너는 브라우저에서 요청이 들어오면 session 객체를 생성해준다고 했습니다. 이 때 브라우저의 고유 식별자(ID)를 받아서 같은 식별자를 가진 session 객체가 있으면 해당 객체를 가져다 쓰고, 없으면 새로 만들어줍니다. 그리고 session 객체를 계속 보관하고 있다가 유효시간이 지나면 무효화를 시키고 무효화가 되기 전이라면 기존 session 객체가 남아있으므로 이미 인증이 된 클라이언트가 맞는지 구분할 수 있게 됩니다. 

 

새로 생성된 객체는 isNew() 메소드에서 'true'를 반환하지만, 만약 한번이라도 다른 JSP 페이지나 서블릿을 거쳐서 왔다면 이미 세션이 생성된 상태가 되어 'false'를 반환하게 되므로 사용 시 주의해야합니다. 

 

 

 

 

아래는 세션을 사용한 로그인 로직을 확인해보기 위해 대충 짜본 코드입니다. 처음 로그인 페이지에 접속했을 때부터 세션에 등록된 userId 값이 있는지 확인하고 없으면 로그인을 진행하고 있으면 로그인이 이미 된 것으로 간주해 메인페이지로 리다이렉트해주는 간단한 코드입니다. 로그아웃 버튼을 눌러 invalid() 메소드를 호출하기 전이나 세션 타임아웃 전까지는 다시 로그인 페이지에 접속해도 바로 메인 페이지로 이동됩니다. 원리만 이해하면 필요에 맞게 사용하면 됩니다. 

 

첫 로그인

 

메인페이지 (다시 로그인 페이지로 들어가도 메인페이지로 리다이렉트)

 

로그아웃 버튼 누르면 다시 로그인창으로 이동

 

* login.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>

	<%
		if (session.getAttribute("userId") != null) {
			response.sendRedirect("main.do");
		}
	%>

	<form action = "join.do" method = "post">
		id : <input type = "text" name = "userId" size = "10"><br/>
		pw : <input type = "text" name = "userPw" size = "10">
		<input type = "submit" value = "전송">
	</form>


</body>
</html>

 

* main.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>

	<%!
		String id;
	%>
	
	<%
		id = (String)session.getAttribute("userId");
	%>
	
	<br/> <%= id %>님 안녕하세요~ 로그인이 돼있습니다~! <br/>
	
	<form action = "logout.do" method = "post">
		<input type = "submit" value = "로그아웃">
	</form>
	
</body>
</html>

 

* Controller.java (서블릿)

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;

@WebServlet("*.do")
public class Controller extends HttpServlet {
	private static final long serialVersionUID = 1L;

	public Controller() {
		super();
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doAction(request, response);
	}

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

		doAction(request, response);

	}

	public void doAction(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		try {
			request.setCharacterEncoding("UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
		}

		// 요청된 페이지 확인
		String uri = request.getRequestURI();

		// session 확인
		HttpSession session = request.getSession();
		String user = (String) session.getAttribute("userId");

		// login.jsp에서 로그인 정보를 입력했을 때 (인증 생략)
		if (uri.equals("/join.do")) {

			// session에 아이디 추가 하고 메인 페이지로 보냄
			String id = request.getParameter("userId");
			session.setAttribute("userId", id);
			response.sendRedirect("main.jsp");

		// 로그아웃 버튼 눌렀을 때
		} else if (uri.equals("/logout.do")){
			
			// 세션 무효화시키고 로그인 페이지로 이동
			session.invalidate();
			response.sendRedirect("login.jsp");
			
		} else {
		
			// 세션 정보에 저장된 아이디 값이 없으면
			if (user == null) {
				System.out.println(uri);
				// 로그인 페이지로 보냄
				response.sendRedirect("login.jsp");

			// 세션 정보에 저장된 아이디 값이 있으면
			} else {
				// 메인 페이지로 보냄
				response.sendRedirect("main.jsp");
			}
		}
	}
}

 


 

  세션?


      WEB-연관된 작업을 수행하고 있는 한 타임의 시간(!)
      DB-두 피어 사이에 데이터를 주고 받기 위해 수립된 통로(!)
 
세션 생성
      : 클라이언트로 부터 최초의 요청 발생시
      생성 시점 :  <%=new Date(session.getCreationTime()) %>
      아이디 : <%=session.getId() %>
      마지막 요청 시간 : <%=new Date(session.getLastAccessedTime()) %>
      <%=session.getMaxInactiveInterval() %>s (세션에 유효된 시간을 반환)
      <%--
      //global 설정으로 session-config 사용 
      	session.setMaxInactiveInterval(2*60);
      --%>
<%--       <%=session.getMaxInactiveInterval() %>s --%>

세션이 유지되는 시간을 120초로 잡음 

web.xml저장된 쿠키이름

  
      ** 세션 유지 방법(session id)
      session tracking mode
      1) Cookie : 양 피어가 서로를 식별하기 위한 식별자(session ID)를 쿠키의 형태로 저장하는 구조.
       <%=session.getId() %>, ${cookie.JSESSIONID.value}
      2) URL : <a href="sessionDesc.jsp;jsessionid=<%=session.getId() %>">세션유지</a>
        매트릭스 변수 중 세션 파라미터를 통해 세션 아이디를 유지하는 구조(보안 취약성)
      3) SSL : secure protocol을 사용하는 경우 제한적으로 사용됨(암호화->openSSL에서 확인).

<%=session.getId() %>, ${cookie.JSESSIONID.value}--> 세션아이디와 쿠키값
localhost에서 확인되었음 f12번눌러서

 

 

 

크롬에서 모든쿠키차단하니깐 쿠키아이디가  사라짐

다시 크롬설정 기본으로돌리고 새로고침하면 계속 세션정보와 쿠키정보가 바뀐다!! (sessionDesc.jsp)
세션이 계속바뀌는것에 대한 이유는 > > 세션유지가 안된다는 이야기 즉 쿠키를 통해서 세션이 유지가 안된다는 거

누르니깐 세션유지됌

<a href="sessionDesc.jsp;jsessionid=<%=session.getId() %>" 이 하이퍼링크를 추가해서 이 링크를 통해서 세션아이디를 가져왓기때문이다. 

하지만 

line에 세션아이디가 노출되서 보안에 취약한점이 보임

 

 

세션 소멸
      1) 명시적 로그아웃 : <% session.invalidate(); %>

     명시적로그아웃추가 하니깐 세션이 계속바뀜 !! 


      2) Timeout 설정
         : 세션 생성 후 다음 요청이 발생할때 timeout 이내 시간 안에 요청이 발생하면,
         세션이 유지되는 구조.
      3) 브라우저 종료
      4) 쿠키 삭제 --> 즉시만료가 아닌 timeout 체킹 이후 만료.