티스토리 뷰
Cookie
Cookie는 HTTP의 속성 중 Connectionless, Stateless 를 해결하기 위한 용도로 사용된다.
- Cookie를 사용함으로써 서버에선 받은 HTTP 요청이 어떠한 정보를 가진 요청이라는 것을 인식할 수 있다. 즉, HTTP 통신 간에 유지하려는 정보가 있는 경우 사용된다.
Cookie는 클라이언트 브라우저(Local)에 저장되는 Key-Value 형태의 데이터이다.
- 서버 측에서 발급하여 클라이언트에게 보내 줌으로써 활용한다. 발급할 때, key-value 말고도 유효한 시간을 정의하여 만료되는 시간을 정할 수도 있다. 또한, path 및 domain 등을 설정하여 특정 주소에서만 사용될 수 있도록 할 수 있다.
- 즉, 유효한 시간까지는 브라우저가 종료되더라도 Cookie의 정보가 남아 계속해서 사용할 수 있다.
- 따로 사용자가 Cookie를 사용한다는 것을 인식할 필요 없이 서버에서 발급되어 브라우저가 자동으로 사용하게 된다.
동작방식은 다음과 같다.
Client가 Server로 요청을 보낸다.
Server에서 request header에 cookie key의 value를 확인한다. 데이터가 있으면 Server에서 원하는 데이터(Server에서 설정한 Cookie)가 있는지 확인한다.
- 없으면, Cookie를 발급한다. Response header에 set-cookie key의 value로 cookie의 key-value 데이터를 설정한다.
- 있으면, 해당 Cookie를 사용한다.
Client (browser)에서 response를 받았을 때, set-cookie 가 있으면 로컬의 쿠키 저장소에 저장한다.
Cookie 값의 path, domain, max-age 속성들을 확인한 후, 그것에 맞는 request를 보낼 때, request header의 cookie 에 값을 넣어 요청한다.
Cookie는 다양한 곳에서 사용된다.
보안적으로 중요하지 않아도 되면서, 서버에서 클라이언트의 정보(행동, 요청)를 트랙킹 하고 싶은 경우 사용된다.
- Cookie의 정보는 HTTP header에 노출되므로 보안적으로 중요한 정보(ex. password)는 담으면 안된다.
예제
- 로그인 시, 아이디/비밀번호 저장 여부 (자동 로그인)
- 비로그인 유저의 쇼핑몰의 장바구니 기능
- 팝업 창 "하루동안 보지 않기" 같은 기능
Cookie 설정 값
- MDN 문서에 Cookie의 용도와 설정 값 등이 정확히 나와있다.
Cookie 설정 정보
- name : Cookie의 이름 (key)
- value: Cookie 담고싶은 값
- Expires/max-age : Cookie의 만료 시간 결정. seconds 단위로 설정된다. 만약 설정하지 않거나 0으로 설정하면, session이 끝날 때까지(브라우저 종료 시)만 유지된다.
- domain: Cookie가 사용될 domain 이름. 예를 들어 github.com 로 설정하면, github.com 의 모든 서브 domain에서 해당 cookie의 사용이 가능하다.
- path : Cookie가 사용될 수 있는 경로. 예를 들어 / 로 설정한 경우, domain 내 모든 경로에서 Cookie 사용이 가능하다.
- secure: HTTPS (secure connection)에서만 cookie를 사용할 지 결정(boolean). Cookie 유출을 막기 위한 용도.
- httponly: HTTP 프로토콜에서만 cookie를 사용할 지 결정(boolean). secure 와 비슷하게 Cookie 유출을 막기 위한 용도로 XSS 공격을 막기 위해 사용한다. 더 자세히 말하자면, javascript의 Document.cookie 를 사용하지 못하게 막아 Cookie의 잘못된 유출을 막는다.
Spring example
- Request 쿠키 값 가져오기
-
// 1 - Using HttpServletRequest @GetMapping public String getHomePage(HttpServletRequest request) { var cookies = request.getCookies(); // ... } // 2 - Using CookieValue annotation @GetMapping public String getHomePage(@CookieValue(value = KEY, required = true) Cookie memberCookie) { // must have cookie -> If don't have cookie? => Exception (default) // 만약 없어도 허용가능하게 하고 싶은 겨우, required = false 옵션 사용 // ... }
- Response 쿠키 값 설정하기
-
@GetMapping private String getHomePage(HttpServletResponse response) { // 1 var permanentExampleCookie = new Cookie("Permanent-Cookie-key", "Permanent-Cookie-value"); permanentExampleCookie.setMaxAge(3600); // seconds = cookie expired time permanentExampleCookie.setPath("/"); response.addCookie(permanentExampleCookie); // 2 var sessionExampleCookie = new Cookie("Session-Cookie-key", "Session-Cookie-value"); sessionExampleCookie.setPath("/"); sessionExampleCookie.setHttpOnly(true); // protect XSS attack response.addCookie(sessionExampleCookie); // 3 var memberId = sequenceGenerator.getNext(); var newMember = Member.create(memberId, "MEMBER " + memberId); memberRepository.save(newMember); var memberIdentityCookie = new Cookie(KEY, String.valueOf(memberId)); memberIdentityCookie.setMaxAge(3600); memberIdentityCookie.setPath("/"); memberIdentityCookie.setHttpOnly(true); response.addCookie(memberIdentityCookie); // .... }
Session
세션은 Cookie를 사용하는(기반으로 하는) 기술로, Cookie의 로컬 저장으로 인한 보안적 문제를 해결하기 위한 기술이다.
- 서버에서 클라이언트를 구분하기 위해 Session id를 부여하여 브라우저가 서버에 접속해 브라우저를 종료할 때까지 인증상태를 유지한다. → 브라우저에서 Cookie와 같이 Session id를 저장해 관리한다. Session id는 Cookie의 key로써 JSESSIONID 로 저장된다.
- Session id에 연관된 정보들을 서버의 세션 저장소에 저장한다. 그렇기에 모든 정보를 로컬에 저장하는 Cookie와 달리 보안성이 더 우수하다.
- 하지만 클라이언트 및 요청이 많아짐에 따라 서버 세션 저장소(메모리)를 차지하기 때문에 서버에 과부하를 줄 수 있다. → 성능 저하의 요인이 되기도 한다.
Cookie와 많이 비교되곤 하는데, 사실 통신 원리 자체는 Cookie와 유사하다. 차이를 자세히 살펴보면 다음과 같다.
- Cookie는 정보를 로컬에 저장하지만, Session은 정보를 서버의 세션 저장소에 저장한다. 정확히 말하자면 Session id는 Cookie에 저장되지만, Session id에 따른 추가 정보들은 서버에 저장한다.
- Cookie는 로컬에 저장하기 때문에 개수 및 용량 제한이 있으나, Session은 없다.
- Cookie는 바로 header로 담겨 사용이 되기 때문에 빠르다. Session은 Session id를 받아 저장소로 부터 정보를 가져와야 하기 때문에 Cookie보단 느리다.
- Cookie는 header에 모든 정보가 저장되어 노출되기 때문에 보안적으로 취약하나, Session은 정보를 서버의 Session 저장소에 저장하므로 보안적으로 Cookie보다 우수하다.
Spring example
Request session 값 가져오기
@GetMapping("/get-session")
public String getSession(HttpSession session) {
var sessionInfo = session.getAttribute(KEY);
// ...
}
Response session 설정하기
@GetMapping("/set-session")
public String setSession (HttpSession session) {
session.setAttribute(KEY, Member.create(sequenceGenerator.getNext(), "name"));
session.setMaxInactiveInterval(60 * 10);
// ...
}
JWT와 차이
Session을 보다보면 JWT와 유사하다는 생각이 든다. 어떠한 유저를 인식하기 위해 header에 정보를 넣어 사용한다는 것이.
하지만 차이는 존재한다.
Session은 Session id에 모든 정보를 가지고 있지 않다. 정보를 찾아낼 수 있는 key만 갖고 있고, 그것에 따른 정보는 세션 저장소를 참조해야한다. JWT는 그 값에 암호화된 모든 정보를 가지고 있다.
- 즉, Session은 정보를 찾기 위해 세션 저장소를 참조해야 하지만, JWT는 복호화 하면 된다.
프로세스 자체는 JWT가 깔끔해보이고, 따로 세션 저장소도 구성할 필요 없이 복호화만으로 정보를 사용할 수 있기에 좋아보인다.
- 하지만 내포하는 정보가 많아지면 많아질수록 JWT의 Payload가 커지고 결국엔 JWT 길이가 길어지게 된다. 결국엔 HTTP header 자체가 무거워지고, HTTP request 자체가 무거워져 서버 및 네트워크 부하가 높아진다는 문제점이 있다.
- 많은 정보를 저장하는 예시 (딱봐도 엄청나게 길어보인다)
References
'Development > Server' 카테고리의 다른 글
[OpenTelemetry] 1. Observability와 용어들 (0) | 2022.07.06 |
---|---|
Linux File Permission (0) | 2022.04.05 |
Port foward 하기 (0) | 2021.07.04 |
Telemetry (Logging stack) (0) | 2021.05.07 |
웹서버(Web Server) 와 웹 어플리케이션 서버 (WAS) (4) | 2021.01.21 |
- Total
- Today
- Yesterday
- java
- Algorithm
- MySQL
- Kubernetes
- 비동기
- Spring boot
- gradle
- python
- Intellij
- 하루
- docker
- 클린 아키텍처
- tag
- Log
- 일상
- 알고리즘
- Clean Architecture
- 로그
- 백준
- Istio
- container
- jasync
- boj
- Spring
- hexagonal architecture
- HTTP
- WebFlux
- k8s
- c++
- 쿠버네티스
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |