기타 개발

쿠키, 세션과 JWT

Junheehee 2022. 5. 7. 22:48

오늘은 쿠키, 세션, JWT를 알아보자.

 

 

- 배경

http프로토콜의 특징인 stateless 때문에 서버는 유저정보를 유지하고 있지 못한다. 연결이 끊나면 서버는 이전 상태를 보존하지 않는다.

그래서 유저 입장에선 똑같은 사이트를 여러번 방문해도, 서버 입장에선 유저가 매번 처음 방문한 것처럼 받아드린다.

이 특징 때문에 불편한 상황이 발생한다.

 

- 페이지를 이동할 때마다, 매번 로그인을 해야하나?

 

- 쿠키(Cookie)

 

Using HTTP cookies - HTTP | MDN

An HTTP cookie (web cookie, browser cookie) is a small piece of data that a server sends to a user's web browser. The browser may store the cookie and send it back to the same server with later requests. Typically, an HTTP cookie is used to tell if two req

developer.mozilla.org

쿠키는 클라이언트와 서버가 주고받는 작은 데이터이다.

페이지에 방문했을 때 유저의 정보는 브라우저에 쿠키로 저장되고, 유저가 웹 페이지를 재방문했을 때, 더 좋은 유저 경험을 제공해준다. 페이스북같은 기업에선 유저 정보를 트래킹하는데 사용하기도 한다.

 

RFC 6265 명세는 쿠키를 http의 일부로 정의하고 있다.

따라서 http의 headers를 보면 서버와 클라이언트가 쿠키를 어떻게 주고 받는지 알 수 있다.

 

RFC 6265 - HTTP State Management Mechanism

 

datatracker.ietf.org

 

 

쿠키는 보통 웹서버에서 생성된다.

웹 서버에서 생성된 쿠키는 HTTP Response Headers 안에 set-cookie를 통해 넣어서 전달된다.

set-cookie

브라우저는 set-cookie로 전달 받은 쿠키를 저장한다.

그리고 동일한 사이트에 접속할 때마다 자동으로 HTTP Request Headers 안에 cookie를 넣어 보낸다.

cookie

쿠키는 맨앞의 name=value말고도 여러가지 옵션을 가지고 있다.

이 옵션은 ;를 통해 구분된다.

 

개발자 도구를 통해 쿠키를 분석해보자.

cookie in browser

- Path

이 경로나 하위 경로에 있는 페이지만 쿠키에 접근할 수 있다. 절대 경로이어야 하고, 기본값은 현재 경로이다.

 

- Domain

쿠키에 접근 가능한 도메인을 지정한다. Domain 옵션에 아무 값도 넣지 않았다면, 쿠키를 설정한 도메인에서만 쿠키에 접근할 수 있다.

 

ex) Domain이 www.naver.com 이고, 이고 Path가 /인 쿠키는 www.naver.com이나 www.naver.com/test에서 접근 가능하다.

 

- Expire / Max-Age

쿠키의 유효기간이 명시되어 있다. 유효기간에 따라 쿠키는 두가지로 구분된다. Session Cookie

        이 쿠키는 현재 세션이 종료되면 삭제된다.

     - Permanent Cookie

        이 쿠키는 expire나 max-age로 정해진 시간이 지나면 삭제된다.

 

- HttpOnly

쿠키는 Document.cookie 처럼 자바스크립트로 제어 가능하기 때문에, XSS 위험에 노출되어 있다. 악성 스크립트 파일이 쿠키를 악용할 수 있기 때문이다. 이를 막아주는 속성이 HttpOnly이다. 이 속성을 사용하면 쿠키를 자바스크립트로 제어할 수 없다.

 

- Secure

이 옵션을 설정하면 HTTPS로 통신하는 경우에만 쿠키가 전송된다.

 

- Samesite

또 다른 보안 속성인 samesite 옵션은 크로스 사이트 요청 위조(cross-site request forgery, CSRF) 공격을 막기 위해 만들어진 옵션이다. (다른 사이트에서 쿠키를 이용할 위험성)

 

쿠키 외에 브라우저에 데이터를 저장할 수 있는 곳은 로컬스토리지 등이 있다.

차이점은 사이트에 접속할 때마다 해당하는 쿠키들이 자동으로 서버에 보내지는 반면에 로컬스토리지는 그렇지 않다는 것이다. (서버와의 통신에서 주고받는 점 때문의 쿠키의 최대 크기는 4kb이다.)

 

- 세션

사실 세션과 JWT는 쿠키와 결이 달라서 비교하는 것에는 무리가 있다.

쿠키는 브라우저가 정보를 기억하는 방법이고 세션과 JWT는 인증 방식이다.

auth by session

ex) 로그인

클라이언트에서 서버로 아이디와 비밀번호를 전달

-> 서버에서 클라이언트에서 받은 정보로 세션 id를 생성후 db에 저장

-> 세션 id를 쿠키에 담아 브라우저에 전달

-> 브라우저에 세션 id가 담긴 쿠키 저장

-> 해당 페이지를 방문하면, 브라우저가 세션 id가 저장된 쿠키를 서버에 보냄

-> 서버는 db에 해당 세션id가 존재하는지 조회

-> 결과를 브라우저의 전달

 

- 세션 id는 유저에 따라 동일하게 생성될 수도 있고, 알고리즘을 추가해 랜덤값으로 생성되기도 한다.

- 중요한 것은 이 id값을 db에 저장하고 조회한다는 점이다.

- db에 세션id를 저장하기 때문에서버는 특정 유저의 연결을 끊을 수도 있고, 현재 몇명이 접속해있는지도 파악 가능하다.

- db는 redis를 많이 이용한다.

 

- JWT

보통 HTTP Headers의 Authentication에 Bearer를 붙여서 주고받는다.

https://stackoverflow.com/questions/33265812/best-http-authorization-header-type-for-jwt

auth by jwt

ex) 로그인

클라이언트에서 서버로 아이디와 비밀번호를 전달

-> 서버에서 클라이언트에서 받은 정보로 jwt생성, db저장 x

-> jwt를 클라이언트에 전달

-> 브라우저에 받은 jwt를 쿠키에 저장

-> 해당 페이지를 방문하면, 브라우저가 jwt를 서버에 보냄

-> 서버는 db에 해당 jwt가 유효한지 검사

-> 결과를 브라우저의 전달

 

 

- jwt의 구조

 

JWT 구조

해당 정보를 base64 인코딩한 것이다.

 

1. Header

   - type: 토큰 타입

   - alg: 어떤 해싱 알고리즘을 사용했는지

 

2. Payload

   담고 있는 실질적인 정보, 하나하나를 클레임이라 부른다.

 

3. Signature

  Header의 인코딩값과, Payload의 인코딩값을 합친후 서버에 있는 비밀키로 해쉬를 하여 생성합니다.

 

로그인을 예시로 jwt 생성 과정을 조금 자세히 살펴보자.

1. 서버가 아이디와 비밀번호를 받으면 당연히 db를 조회하며 해당 아이디가 존재하는지, 비밀번호가 맞는지 먼저 살펴볼 것이다.

2. 맞다면 jwt를 생성한다. Header에는 토큰 타입과 어떤 해싱 알고리즘을 사용했는지, Payload에는 유저를 판별할 수 있는 고유값이나 토큰 만료기간 등 전달하고 싶은 정보를 담는다. 그리고 Header와 Payload를 base64로 인코딩한다.

그러면 (인코딩 된 Header).(인코딩 된 Payload) 꼴이 되는데 이 값을 위에서 정한 해싱알고리즘으로 사인한다. 이 때 서버에 저장되어 있는 비밀키를 사용한다.

함수로 표현하면 Signautre = 해시 ( 인코딩된Header.인코딩된Payload, 서버에 있는 비밀키) 이다.

이렇게 만들어진 Signautre도 base64로 인코딩해서 붙인다.

결과적으로 jwt는 (인코딩 된 Header).(인코딩 된 Payload).(인코딩 된 Signature) 이다.

3. 생성된 jwt는 http headers에 담겨 브라우저에 전달된다.

4. 브라우저는 받은 jwt를 cookie에 저장한다.

 

만약 jwt를 이용하는 웹페이지를 이용한다면,

1. 브라우저는 쿠키에 저장된 jwt를 서버에 보낸다.

2. 서버는 jwt가 유효한지 검사한다.

검사하는 방법은 jwt를 생성하는 것과 비슷하다. 받은 jwt의 (인코딩 된 Header).(인코딩 된 Payload)와 서버의 비밀키로 해싱한 뒤 생성된 값을 받은 jwt의 signautre와 비교한다. 동일하다면 서버는 jwt로 유저를 인증했으니 브라우저에 필요한 유저 정보를 전달해 줄 것이다.

 

아래는 jwt를 만들어볼 수 있는 사이트다.

 

JWT.IO

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.

jwt.io

사실 jwt의 payload는 단순히 base64로 인코딩한 것이기 때문에 중요한 정보는 넣지 않는 것이 바람직하다.

 

이렇게 세션과 JWT는 인증 방식 중 하나이고 이 과정에서 쿠키를 이용하기도 한다.

세션id나 JWT를 쿠키에 실어서(혹은 body나 headers) 보낼 수도 있고, 받은 데이터를 쿠키(혹은 로컬 스토리지)에 저장할 수도 있다.

보통은 로컬스토리지의 보안상 취약점 때문에 쿠키에 많이 저장한다.

 

- 더 공부할 만한 것

1. 트래킹, 마케팅

쿠키로 유저정보를 트래킹해서 마케팅에 이용한다. 쿠키를 만든는 곳에 따라 퍼스트 파티 쿠키, 서드 파티 쿠키로 나뉜다.

2023년에 구글이 서드 파티 쿠키를 금지한다고 발표해서 디지털 마케팅에 큰 혼란이 올 것으로 예상된다.

https://www.techtarget.com/searchcustomerexperience/tip/Will-Google-kill-third-party-cookies

쿠키로 어떻게 트래킹하고 어떻게 마케팅에 이용하는가?

 

2. 보안

쿠키에 HttpOnly와 Secure, SameSite 등으로 보안 문제를 어느정도 해결할 수 있다곤 하지만, 쿠키가 완벽히 안전하진 않다.

HttpOnly를 우회하는 xst 공격도 등장했고, 반대로 CSRF를 효과적으로 방어하기 위해 double submit cookie가 등장하기도 했다.

보안과 해킹을 흐름으로 공부하기. 해킹을 막기 위해 보안이 생기고, 그걸 해킹하고, 다시 보안 방법이 나오고..

키워드) xss, csrf

 

3. DB

redis가 NoSQL이여서 빠르다?, SQL과 NoSQL의 차이, 데이터 베이스의 구조

 

4. base64

 

Base64 Decode and Encode - Online

Decode from Base64 format or encode into it with various advanced options. Our site has an easy to use online tool to convert your data.

www.base64decode.org

'기타 개발' 카테고리의 다른 글

Sync vs Async / Blocking vs Non-blocking  (0) 2022.06.15
REST API  (2) 2022.05.25
웹소켓(Web Socket)  (4) 2022.05.18
1. 인터넷은 무엇일까  (1) 2021.11.10
0. 시작하며  (2) 2021.11.09