Session, HttpSession 인터페이스. 쿠키

최동민·2022년 6월 6일
0

Spring 수업정리

목록 보기
16/47

Java HttpSession(javax.Servlet.Http) 소개

HttpSession은 Java의 인터페이스(interface)이며, 이를 사용하여 세션(session)을 제어할 수 있습니다.

session은 쿠키(cookie)의 트래픽(traffic) 이슈(issue)와 cookie 변경으로 인한 보안 issue를 해결하기 위해 등장했습니다.

session

  • session은 사전적 의미로 서버(server)와 클라이언트(client) 간에 반영구적으로 상호 작용하는 정보 교환입니다.
  • session은 server로 요청(request) 하는 client를 구별하기 위해 server에 저장되는 정보입니다.
  • session은 client에 저장되는 쿠키(cookie)와 다르게 server에 저장되므로 관리가 용이하고 효율적이며 보안에 강합니다.
  • server는 client request에 session-id를 생성하여 server와 client 브라우저(browser) 메모리(memory)에 cookie로 저장합니다.
  • 위 cookie는 일반적인 cookie가 아닌 session cookie이며, 인 메모리(in-memory) cookie 또는 임시(transient) cookie, 반영구(non-persistent) cookie로 불립니다.
  • session cookie는 server가 종료되거나, 유효기간이 만료하거나, client browser가 종료되면 삭제됩니다.
  • session의 단점은 server resource를 사용하므로 server에 부담을 줄 수 있으며, 로드 밸런싱(load balancing) 시스템(system)에서 session 처리가 쉽지 않다는 것입니다.

session mechanics

  1. client가 server에 리소스(resource)를 request 합니다.
  2. server는 client가 request 한 request-header의 session cookie를 통해 session-id를 확인합니다.
  3. session-id가 존재하면, server는 session-id가 유효한지 확인 후 client의 request를 처리하고 응답(response) 합니다.
  4. session-id가 존재하지 않으면, server는 set-cookie를 통해 session-id를 생성한 후 response-header에 추가하여 client에 response 합니다.
  5. 위 4번 항목 처리 후 client는 server에 request 시, server로부터 response 한 session-id를 request-header에 추가하여 request 합니다.
  • session 종료 시기
  1. 타임아웃(timeout)
  2. session 객체(object)의 invalidate() 호출
  3. 애플리케이션(application) 또는 server 종료

HttpSession

  • HttpSession은 client request에서 client를 식별하고, 해당 client 정보를 저장하는 방법을 제공하는 Java의 public interface입니다.
  • HttpSession interface를 사용하는 서블릿 컨테이너(servlet container)는 server와 client 간의 session을 제어합니다.
    • servlet container는 웹(web) container라고도 불리며, Tomcat, JBoss(현재 WildFly), Jetty 등이 대표적입니다.
    • servlet container와 servlet은 다릅니다.
      • servlet container는 server에서 servlet 생명 주기(life cycle) 관리, request에 따른 스레드(thread) 생성, 동적(dynamic) resource(JSP, servlet 등) 생성 등 servlet과 상호 작용하는 web server의 일부입니다.
      • servlet은 javax.servlet package에 정의된 interface이며, JVM(java virtual machine) 내에서 실행되는 web application의 작은 조각입니다.
  • HttpSession object 생성
    • {HttpServletRequestObject}.getSession() : // 기존 session이 있으면 기존 session object를, 없으면 새로 생성 후 반환
    • {HttpServletRequestObject}.getSession(false) // 기존 session이 있으면 기존 session object를, 없으면 null 반환
  • HttpSession Method
    • setAttribute(String, Object)
    • getAttribute(): Object
    • getCreationTime(): long
    • getLastAccessedTime(): long
    • setMaxInactiveInterval(int second) // client가 설정 시간 동안 request가 없으면 session 만료
    • getMaxInactiveInterval(): int
      invalidate() : // session 종료(session에 속한 속성들도 함께 제거)
    • getId() : String // SessionId 반환
Tomcat은 WAS? No! Just Servlet Container!]
JAVAEE는 엔터프라이즈 어플리케이션을 위해 만든 표준이고, 수많은 클래스/인터페이스로 정의되어 있습니다.
JAVAEE 6.0의 스펙을 보면, Web Services, Web Application, Enterprise Application, Management and Security 기술들을 정의하고 있습니다.
그리고 이 스펙을 모두 구현한 모델을 WAS라고 칭합니다. 
우리가 흔히 WAS로 알고 있는 tomcat은 JAVAEE 스펙의 일부만 구현하고 있어, WAS가 아니라 Servlet Container 입니다.

즉 우리가 웹어플리케이션을 개발할 때 사용하는 HttpSession도 Servlet Container가 생성한 인스턴스이다.
Spring은 Servlet Container가 만든 HttpSession을 주입할 뿐, HttpSession을 생성하는 주체는 Servlet Container이다.
(참고로 SpringSession을 이용한다면 Servlet Container가 생성한 구현체가 아니라 SpringSession이 생성한 구현체가 될 것.

HttpSession은 언제 만들어질까?

모든 요청에 대해 Session을 만들까?
아니다. Session을 만드는 것 자체도 부담이 가는 일이기 때문에, Session을 사용할 때만 생성한다.

Spring Web MVC에서는 HttpSession을 주입해야 할 때, 내부적으로 Servlet Container에게 Session을 달라고 한다.

httpServletRequest.getSession()

그리고 그 때 Servlet Container가 HttpSession을 생성해준다. Spring이 Servlet Container에게 Session을 달라고 하는 시점은 HttpSession을 사용하는 방법에 따라 약간씩 다르다.

HttpSession을 주입받는다고 선언하는 것만으로는 Servlet Container에게 Session을 달라고 요청하지 않는다. setAttribute 혹은 getAttribute 같은 api를 호출하는 시점에 요청/생성한다.

이렇게 메소드에서 매개변수를 통해 주입받는 방식으로 구현하는 경우엔, 선언시에 Servlet Container에게 Session을 달라고 요청한다. 따라서 위의 예제에서는 getList 메소드를 호출하는 즉시 Session이 요청/생성된다.


HttpSession 인터페이스는 둘 이상의 page request에서 사용자를 식별하거나, 웹 사이트를 방문하고 해당 사용자에 대한 정보를 저장하는 방법을 제공한다.

Servlet container는 HttpSession를 사용하여 HTTP client - HTTP server 간의 세션을 생성한다. 이 때, 세션은 한 명의 사용자에 해당한다. 서버는 Cookie, rewriting URL와 같은 방법으로 세션을 유지하면서 관리할 수 있다. 객체를 세션에 바인딩하여 사용자 정보를 유지할 수 있다.

관련 메서드

// 값 저장 HttpSession's setAttribute("Key", Value)

  • "Key"를 사용하여 객체를 세션에 바인딩한다.
    Value는 값으로 들어올 자료형을 예측할 수 없기에 Object형으로 업캐스팅하여 모두 받아낸다.

// 값 얻기 HttpSession's getAttribute("Key")

  • "Key"로 바인딩된 객체를 돌려주고, "Key"로 바인딩된 객체가 없다면 null를 돌려준다.
    Value는 세션을 저장할 때 Object형으로 업캐스팅을 했으므로, 가져올 땐 원래대로 다운캐스팅 해야 한다.

// 생성 HttpServletRequest's getSession(true)

  • 이미 세션이 있다면 그 세션을 돌려주고, 세션이 없으면 새로운 세션을 생성한다.
    request.getSession()로 쓸 수 있다.
    HttpSession session = request.getSession();

// 생성 HttpServletRequest's getSession(false)

  • 이미 세션이 있다면 그 세션을 돌려주고, 세션이 없으면 null을 돌려준다.
    HttpSession session = request.getSession(false);

// 값 제거

  • session.removeAttribute(String name);

// 특정 이름의 속성 제거

  • session.invalidate(); // binding 되어 있는 모든 속성 제거

정리

[Session]

  • 방문자가 웹 서버에 접속해 있는 상태
  • WAS의 메모리에 Object의 형태로 저장
  • 메모리가 허용하는 용량까지 제한없이 저장가능

[동작순서]

  • 클라이언트가 페이지 요청
  • 접근한 클라이언트의 쿠키를 확인하여 해당 session-id를 보냈는지 확인
  • session-id를 생성해 클라이언트에게 돌려줌
  • 서버에서 클라이언트로 돌려준 session-id를 쿠키를 사용해 서버에 저장 (쿠키이름: JSESSIONID)
  • 클라이언트 재 접속시, 이 쿠키를 이용하여 session-id값을 서버에 전달.

[특징]

  • 웹 서버에 상태를 유지하기위한 정보를 저장
  • 웹 서버에 저장되는 쿠키(세션쿠키)
  • 서버에서 세션을 삭제 했을때만 삭제가 되므로, 쿠키보다 비교적 보안이 좋다.
  • 각 클라이언트 고유 sesison id를 부여


잘 이해 안되면 또 정리

HttpSession 객체

  • HTTP 프로토콜은 비연결형(stateless) 프로토콜
  • 연결 -> 요청 -> 응답 -> 종료
  • 연속적인 사용자 정보가 보관되지 않음ex ) 로그인 상태, 장바구니

해결방안

  • 별도의 수단을 통해 각각의 클라이언트를 구분
  • 클라이언트 별로 해당 정보를 유지
  • 어떻게 클라이언트를 구분할 것인가 ? -> 쿠키와 세션으로 해결 가능

쿠키 vs 세션

쿠키 :

  • 브라우저를 통해 클라이언트에 저장되는 사용자 정보
  • (name, value) 쌍으로 이루어진 정보
  • 초기에 웹 서버에 의해 HTTP Header에 포함되어 클라이언트에게 전송
  • 이후에 접속마다 클라이언트가 웹 서버에게 재전송
  • 보안적 취약성으로 인해 중요 정보를 저장하지 않아야 함

세션 :

  • 사용자 정보를 서버에 저장
  • 클라이언트의 최초 접속 시 새로운 세션을 생성하고 세션 ID 전송
  • 이후 접속마다 클라이언트가 세션 ID 재전송
  • 서버는 세션 ID에 해당하는 세션 정보를 획득
  • 세션 ID 전송 수단으로 쿠키를 사용할 수 있음

세션 관리

  • 대부분의 세션 관련 작업은 container가 처리
  • Servlet은 request로 부터 HttpSession 객체를 제공받음
ex ) HttpSession session = request.getSession();

생성된 세션이 없었던 경우

  • Container에 의해 처리
  • 새로운 세션 ID 생성- 세션 ID를 클라이언트에게 보낼 준비
  • 새로운 HttpSession 객체 생성 후 Servlet에 제공

기존 세션이 있는 경우

  • Request에 포함된 세션 ID에 해당하는 HttpSession 객체를 찾아서 제공

HttpSession Interface

  • boolean isNew() : 이번 요청으로 새로운 세션이 생성되었는지의 여부를 리턴
  • String getid() : 현재의 세션 ID를 리턴
  • void invalidate() : 현재 세션 종료
  • long getCreationTime() : 세션이 생성된 시간 제공
    -long getLastAccessedTime() : 마지막으로 세션에 관련된 클라이언트가 요청을 보낸 시간 제공
    -void setMaxInactiveInterval(int) : 초단위로 최대 유휴기간 설정
    -int getMaxInactiveInterval() : 초단위로 설정된 최대 유휴기간 리턴
  • void setAttribute(String, Obect)
  • Object getAttribute(String)

세션 Lifecycle

  • 생성 : 최초로 request.getSession()이 호출될 때 container가 생성
  • 사용 : 클라이언트가 세션 ID를 이용해 접속, request.getSession()을 통해 사용중인 HttpSession 객체 획득 후 사용
  • 종료 : invalidate()가 호출되거나, 세션이 타임아웃 되었을 때 container가 소멸 

Q.

HttpSession.getAttribute("user")

  • 사용자 A가 접속해도 "uesr" 를 key로 값을 가져오고,
    사용자 B가 접속해도 "user" 를 key로 가져온다.
    같은 key를 쓰는데 어떻게 A 와 B를 구분해서 값을 가져올 수 있을까?

A.

Session은 각 클라이언트 마다 하나씩 생성되어 제공이 된다.
그렇기 때문에 HttpSession.getAttribute("user")를 해도 서로 다른 값이 보이도록 된다.

  • 위키백과
    세션(session)은 컴퓨터 과학에서, 특히 네트워크 분야에서 반영구적이고 상호작용적인 정보 교환을 전제하는 둘 이상의 통신 장치나 컴퓨터와 사용자 간의 대화나 송수신 연결상태를 의미하는 보안적인 다이얼로그(dialogue) 및 시간대를 가리킨다. 따라서 세션은 연결상태를 유지하는 것보다 연결상태의 안정성을 더 중요시 하게 된다.

단순하게 말하면 클라이언트와 서버 간의 연결이 지속적으로 유지되는 상태. 즉, 웹 사이트 탐색하는 시간을 의미한다.

HTTP의 특성은 이러하다.

  1. HTTP는 무상태(Stateless) 프로토콜이다.
  2. 클라이언트와 서버가 요청과 응답을 주고 받으면 연결이 끊어진다.
  3. 클라이언트가 다시 요청하면 서버는 이전 요청을 기억하지 못한다.
  4. 클라이언트와 서버는 서로 상태를 유지하지 않는다.

session의 특성은 다음과 같다.

  1. 클라이언트가 처음 서버에 연결을 하면 어떤 하나의 Session ID가 생성된다.
  2. 이 아이디는 고유한 아이디이다.
  3. 이 아이디를 통해서 서버는 아 이녀석이구나 하고 요청에 대한 응답을 하게 된다.

즉, 클라이언트는 하나의 유일한 주민등록번호와 같은 것을 갖고 있는 것이다.
만약 클라이언트 하나마다 생성되는 아이디가 아예 없다면 어떻게 될까?
최동민이라는 이름으로 은행에서 출금을 하려 할 때에
은행원은 이 최동민이 누구 최동민인지를 알 수가 없다.
식별할 수 있는 고유한 값이 없다는 것이고. 그렇다면 요청에 대한 응답을 서버는 내릴 수가 없을 것이다.

참고 링크

세션 정리
세션 정리
세션 정리
참고링크
로그인이 이루어지는 과정

profile
코드를 두드리면 문이 열린다

0개의 댓글