본문 바로가기

Web Sever 개발과 CS 기초/네트워크 지식

쿠키와 세션의 구조 - 세션 로그인과 JWT 로그인 차이

관련 내용

[스프링] - Spring Security와 JWT 토큰을 이용하여 REST API 인증,인가 구현하기

글의 목적

관련 내용 글에서는 SpringSecurity와 JWT 토큰을 이용한 REST API 인증 인가 구현을 해보았다.

이번 글에서는, 인증과 인가 처리의 필수 요소인 세션과 쿠키 구조에 대해서 알아보고,

세션 로그인과 JWT 로그인의 작동 과정과 장, 단점을 통해서 둘 사이의 어떤 차이가 있는지 알아보자.

쿠키와 세션의 구조

쿠키와 세션의 필요성

HTTP 프로토콜은 Stateless 특성이 있다. 그래서 클라이언트와 서버의 Request Response 통신이 끝나는 순간, 이전 상태를 보존하지 않는다. 장점으로는, 상태를 보관하지 않으므로 클라이언트의 요청에 어느 서버가 응답해도 상관이 없다. 그래서 트래픽이 급증 해도 단순히 서버를 증설해서 해결할 수 있다

단점으로는, 클라이언트의 상태 정보를 저장하지 않기 때문에 클라이언트의 신원과 접근 권한을 매번 확인해야 한다. 이 문제를 해결 하기 위해, 쿠키와 세션을 사용한다.

방법으로는 클라이언트가 처음 로그인을 진행하면, 서버는 이 클라이언트는 로그인 회원이라는 표식이 담긴 쿠키를 클라이언트에게 전달한다. 그 클라이언트는 쿠키를 저장 해놓고, 다음 요청부터는 header에 쿠키 정보를 같이 보낸다. 서버는 헤더에 담긴 쿠키 정보를 통해 로그인한 회원임을 바로 파악할 수 있다.

쿠키 알아보기

쿠키

  • 클라이언트 브라우저에 저장되어 있는 키-값 형식의 데이터
  • 서버가 처음으로 보낸 쿠키를 클라이언트 브라우저에 저장했다가, 헤더에 참조해서 요청을 보냄
  • 최대 300개의 쿠키 저장 가능하고, 각 도메인 당 20개의 쿠키 저장 가능, 하나의 쿠키 값은 4KB이하여야 한다

쿠키 종류

  • 세션 쿠키 : 브라우저가 종료될 때 같이 제거되는 쿠키
  • 영속 쿠키 : Expires 또는 Max-age 옵션을 추가해서, 브라우저가 종료되어도 유지되는 쿠키

쿠키의 구조

  • 이름(name) 쿠키를 구분하는 키 값
  • 값(value) 해당 쿠키의 내용
  • 도메인 쿠키를 전송할 주소
  • 경로(path) 쿠키를 전송할 특정 경로
  • secure - https프로토콜 요청일 경우만 전송
  • HttpOnly - cross-stie 스크립트 공격을 방지한다.

사용 예시

  • 팝업 창 7일 간, 보지 않음 체크
  • 자동 로그인 설정

문제점

로그인 상태를 유지할 때, 쿠키를 사용할 경우, id와 password 정보를 request에 그대로 노출하기 때문에, 해킹의 위험이 높다. 그 문제를 해결하기 위한, 세션에 대해서 알아보자.

세션 알아보기

세션이란

  • 세션은 쿠키를 사용하여 작동하지만, 사용자 정보를 서버에서 관리한다.
  • 서버는 세션 목록에 세션ID와 사용자 정보를 매칭해서 저장하고, 클라이언트에게는 세션 ID만 제공한다.
  • 클라이언트는 request에 세션ID만 작성한 후 서버에게 보내면, 서버에서 세션 ID에 해당하는 유저가 있는 지 확인하여 인증 인가 처리를 결정한다.
  • 보안상 이점은 있지만, 서버에서 사용자 정보를 관리해야 하기 때문에, 메모리 문제가 발생 할 수 있다.
  • 속도도 쿠키보다 느릴 수 있다.
  • 세션 정보를 서버에서 관리하고 있기 때문에, 해킹 시 대처가 쉽다. 서버의 세션 목록에서 해당 클라이언트 세션 정보를 삭제하면 된다.

세션 로그인과 JWT 로그인

세션 로그인

작동 과정

  1. web에서 로그인 정보를 입력해서 서버에 요청하면,
  2. 서버의 DB와 비교하여, 회원이 맞다면, 서버의 세션 목록에, 세션ID와 로그인에 성공한 유저 정보를 매치해서 저장한다.
  3. 그리고 세션 ID를 response Message에 담아서 보낸다. → web에서는 서버에서 보낸 세션 ID를 쿠키에 자동으로 저장한다.
  4. 그 이후 요청부터는, web Request Message에 로그인 정보 없이 세션ID만 붙여서 보내게 된다.
  5. 서버에서는 세션 ID를 통해서, 로그인된 web인지 어떤 유저인지 파악할 수 있게 된다.

로그인 처리를 종료하는 방법

  • 서버에서 세션ID 목록을 삭제한다.
  • 브라우저 자체를 종료해서 쿠키 정보를 없앤다.
  • 세션 ID 유지 시간이 종료된다.

장점

  • web에는 의미 없는 세션ID만 제공하고, 실제 유저에 대한 중요한 정보는 서버의 세션 목록을 통해서 관리하기 때문에, 보안에 안전하다.
  • 특정 유저가 해킹을 당했을 때, 세션 목록에서 해당 유저 정보를 제거하여 접속을 차단할 수 있어 해킹 대처에 좋다.

단점

  • 중요한 정보를 서버의 세션 목록에서 관리하기 때문에, 동시 사용자가 많을 경우, 서버의 메모리에 부담이 갈 수 있다.
  • 또한 로드 밸런싱을 통해, 여러 서버를 운영할 경우, 모든 서버가 공유 할 수 있는 세션 목록 저장소를 두어야 한다. 그렇지 않으면, 로그인이 끊기는 문제가 발생할 수 있다. 그래서 여러 서버가 공유 세션 목록 저장소에 빠르게 접근하기 위해, In-Memory-DB인 레디스를 사용한다.

Redis가 사랑 받는 이유

JWT 로그인

작동 과정

  • web에서 로그인 정보를 담은 Request를 서버에게 보낸다.
  • 서버에서 인증이 완료 되면 JWT 토큰을 보낸다.

<JWT 토큰 구조>

(JWT 토큰의 Header에는 어떤 알고리즘을 통해서 서명을 했는지 정보의 Json을 Base64 URL 인코딩하고, Payload(내용)에는 해당 유저를 구별할 수 있는 id, userName등을 담아 인코딩한다. Signature는 Header와 Payload 서버만 알고 있는 시크릿키를 HS256으로 암호화한 내용을 담는다.)

  1. 클라이언트는 JWT 토큰을 LocalStorage에 저장한다.
  2. 다음 요청부터는, JWT 토큰을 함께 보내서 인증 처리를 대신한다.
  3. 서버에서는 JWT 토큰이 올바른 토큰인지 확인한다.

web에서 보낸 JWT 토큰의 Header와 PayLoad 그리고 서버만 알고 있는 시크릿키를 HS256으로 암호화해서 JWT토큰의 Signature 부분과 일치하는 지 확인한다.

(+ 올바른 토큰인지 확인하는 방법에는 RSA 암호화 방식을 사용하기도 한다.)

  1. JWT토큰이 확인 되면, Payload에 있는 정보를 통해서 해당 유저에 대한 정보를 제공한다.

장점

  • 인증을 위한 서버의 별도의 저장소가 필요 없다. 그래서 확장성이 좋다.
  • 세션 목록을 확인하는 I/O 작업이 없어서 빠른 인증 처리가 가능하다.

단점

  • 토큰의 길이가 길어진다면, web→server 네트워크 통신 부담이 커진다
  • payload 자체는 암호화 된 것이 아니라 단순히 인코딩 된 것이어서, Payload 탈취를 우려해, 중요한 데이터를 넣으면 안 된다.

->커스텀이 가능하기 때문에, 암호화 해서 보낼 수 있다.

  • JWT가 탈취당했을 때, 유효기간이 만료되기 전까지는 탈취된 JWT 입장을 막을 방법이 없다.

->이부분이 가장 큰 취약점이기 때문에, 생각보다 JWT 토큰 로그인 방식이 많이 쓰이지 않는 결정적인 이유이다.


Reference

https://www.popit.kr/jwt-인증은-무엇이고-어떻게-사용해야-할까/

https://devjem.tistory.com/13

https://www.youtube.com/watch?v=XXseiON9CV0&feature=youtu.be

https://interconnection.tistory.com/74

https://cjh5414.github.io/cookie-and-session/