오늘은 어디로 갈까...

Session에 대한 단상(斷想) 본문

낙서

Session에 대한 단상(斷想)

剛宇 2009. 4. 6. 21:45


 HTTP(Hyper Text Transfer Protocol)은 웹상에서 정보를 주고 받을 수 있게 정의한 통신 규약을 말한다. 1996년 1.0 버전이, 1999년 1.1 버전이 발표되었으면, IETF(Internet Engineering Task Force)의 RFC에 자세히 기술되어 있다. 현재 가장 많이 쓰이는 버전은 1.1이다. 사용하는 기본 포트는 80번이다.
 HTTP의 특징(?) 중 한가지가 무상태(Stateless) 즉, 상태 정보를 유지하지 않는다는 것이다. 사용자(Client)는 매번 요청을 할때마다 서버에 접속을 하고, 응듭을 받으면 연결을 끊어버린다. 그래서 서버의 입장에서는 요청을 하는 사용자가 누군지 알지 못하는 슬픈 일이 생긴다. (넌~ 누구냐~?)
 이 상황을 해결하기 위해, 즉 사용자 정보를 식별하기 위해서 일반적으로, Cookie나 Session, URL Rewriting 방법을 사용한다.

 1. Cookie
  - 쿠키는 이름 그대로 과자부스러기이다. 사용자의 컴에 부스러기 같은걸 남기고, 서버에 요청을 보낼때마다 그 부스러기 정보를 포함해서 날려주는것이다.
  - 사용자의 컴에 정보를 남기기 때문에 서버에 부하를 주지 않는 장점이 있지만, 사용자 마음데로 변조가 가능하여 여러 나쁜(?) 용도로 사용되므로, 하찮은(?) 정보만 저장하는것이 관례이다.

  1.1 쿠키 추가하기

 String name = "myCookie";
 String value = "taste";
 Cookie cookie = new Cookie(name, value);
 cookie.setMaxAge(3 * 60); // 3분후 종료
 response.addCookie(cookie);



  1.2 쿠키 가져오기
    - request 객체를 통해 쿠키를 가져올 수 있다.
    cookieInfo.jsp
<%@ page contentType="text/html; charset=UTF-8" %>
<%
	Cookie[] cookies = request.getCookies();
	if (cookies != null) {
		for (Cookie cookie : cookies) {
			out.print(cookie.getName());
			out.print("=");
			out.print(cookie.getValue());
			out.println("<br />");
		}
	}

%>

  1.3 쿠키 변조
    - 쿠키는 사용자 컴에 저장이 된다. 그래서 자바스크립이나 유용한 툴(Cooxie)로 아주 손쉽게 값을 바꿔버릴수가 있다.
    - 사용자 인증같은것을 쿠키로 해버리면, 해당 사이트는 술과 눈물로 나날을 보내야할것이다.
    - 혹시 필요에 의해서 어쩔 수 없이 사용해야한다음, 암호화해서 저장하는게 정신 건강에 좋다.


 2. Session
  - 일반적으로 많이 사용하는 방법어로서, 서버에 Session 객체가 저장되어 있다.
  - 서버에 정보가 저장되어 있어서, 쿠키보다는 서버에 부하를 주지만, 사용자가 마음데로 변조할 수 없어서 안전한 편이다.
  - 세션 생성/소멸 등의 관리는 서버가 알아서 해주므로, 개발자는 편하게 값을 설정하고 가져오기만 한다.
  
  2.1 세션에 값 추가하기
session.setAttribute(name, value);
 
  2.2 세션에가 값 가져오기
Object value = session.getAttribute(name);

 2.3 세션 정보 보기
<%@ page contentType="text/html; charset=UTF-8" %>

세션 아이디 : <%=session.getId()%><br/>
새로 생성되었는지 여부 : <%=session.isNew()%><br/>
생성 시간 : <%=session.getCreationTime()%><br/>
마지막 접근 시간 : <%=session.getLastAccessedTime()%><br/>
최대 유효시간  : <%=session.getMaxInactiveInterval()%>초<br/>


 2.4 짧은 생각
  - 세션은 서버에 저장된다. 그러나, 사용자가 쿠키 사용을 못하게 해놓으면 세션도 사용할 수 없다. 그 이유는 사용자를 구별하기 위한 세션아이디를 쿠키로 저장해놓기 때문이다. 즉, 세션은 쿠키가 작동 가능해야 정상적으로 작동한다.
  - 자바쪽은 일반적으로 JSESSIONID 라는 이름의 쿠키로 세션 아이디값을 사용자에게 저장해놓고, 이 값으로 사용자를 구별한다.

  - 아무 쿠키값도 설정하지 않은 상태에서 저장된 쿠키값을 읽어와서 출력해보자.
* cookieInfo.jsp 출력결과
JSESSIONID=D3196DB07F4BD293D919660E1E468591

  - 세션값을 출력해보자.
* sessionInfo.jsp 출력결과
세션 아이디 : D3196DB07F4BD293D919660E1E468591
새로 생성되었는지 여부 : false
생성 시간 : 1238981960337
마지막 접근 시간 : 1238981964884
최대 유효시간 : 1800초

 두 값을 비교해보면, 쿠키에 저장되어 있는 세션아이디랑, 서버 세션에 저장되어 있는 세션 아이디가 동일하는것을 알 수가 있다.
 여기서 재미있는 발상을 할 수 있는데, 앞에서 쿠키는 쉽게 변조가 가능하다고 했다. 그렇다면 JSESSIONID 값을 변조하면 어떻게 될까? 만약 그 값이 서버에 존재하는 세션 아이다값이라면 그 세션을 마음껏 유린할 수 있는 것이다. 즉 다른 사람의 정보를 마음껏 볼 수 있다는것이다. 생각만 해도 기쁘지만, 사실 찍어서(?) 이 값을 추출해내는것은 거의 불가능하다. 16바이트의 코드를 찍어서 맞출정도면, 로또~를 사는게 훨씬 현명한 선택일것이다.
 그러나, 생각을 달리해서 다른 사용자의 JSESSIONID값을 전송 받을 수 있다면, 손쉽게 그 사람의 세션에 접근할 수 있는것이다. 예를 들어 메일에 해당 사용자의 쿠키값을 읽어서 다른 사이트로 전송하는 악성(?) 스크립트를 넣어서 발송하면, 사용자가 메일을 읽는 순간 그 쿠키값은 노출될것이고, 그 값을 이용해 변조하면 다른 사람 세션을 손에 넣을 수 있는것이다. (요즘은 물론 메일에서 이런 기능을 방지하고 있다. ^^) 생각만 해도 흐믓(?)하다 ^^;;; 흠흠..


3. URL Rewriting
 - 앞의 두 방법은 쿠키를 쓸 수 있어야 작동이가능하다. 그렇다면 쿠키가 허용이 안되는 환경에서는 어떻게 사용자를 구별할 수 있을까? 뭐 예상외로 간단하다. 호출 하는 주소에다 식별 정보를 추가해주면 되는것이다.
 - 일일이 넣어줄려면 귀찮은데, 다행히도  response 객체에서 식별 정보를 추가해주는 encodeURL(String) 메소드를 제공해준다.
<%@ page contentType="text/html; charset=UTF-8" %>
세션 아이디 : <%=session.getId()%><br/>
<a href="<%=response.encodeURL("sessionInfo.jsp")%>">sessionInfo.jsp</a>

 실행해서 링크 주소를 살표보면 뭔가가 추가되었을것이다.
즉 response.encodeURL("sessionInfo.jsp")의 값이 sessionInfo.jsp;jsessionid=7A0067093CDA26448A2374CF0FDE42FB  로 변경된것을 알 수 있다. 이 jsessionid=7A0067093CDA26448A2374CF0FDE42FB 이 식별자인것이다.


4. 넋두리
 - 일반적으로 2번 세션방식을 많이 사용한다. 일부 사이트는 WAS에서 기본적으로 제공하는 세션을 이용하지 않고, 자체적으로 세션 비슷무리한것을 만들어 사용하기도 하는데, 근본 원리는 2번과 비슷하다고 보면 된다.
 - 어떤분께서 방명록에 HttpClient 에서 세션을 어떻게 유지하냐고 물어봤기 때문이 이런 글을 작성하게 되었다. 2번 같은 방법이라면, HttpClient에 쿠키 가능하게 설정해주면 알아서 세션 유지가 되는것이다. 즉, client.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);  이렇게 설정해주면~ 뭐~ 대충~ 되는것이다. ^^;