브라우저 저장소 (Web Storage)
Web Storage란 HTML5에서 추가된 해당 도메인과 관련된 특정 데이터를 서버가 아니라 클라이언트 웹브라우저에 저장할 수 있도록 제공하는 기능을 의미한다. 이는 쿠키(Cookie)와 비슷한 기능이다.
브라우저 저장소는 키/값 쌍으로 데이터를 저장하고, 키를 기반으로 데이터를 조회하는 패턴이다. 영구저장소(LocalStorage)와 임시저장소(SessionStorage)를 따로 두어 데이터의 지속성을 구분할 수 있어 응용 환경에 맞는 선택이 가능하다. 또, 쿠키와 마찬가지로 사이트의 도메인 단위로 접근이 제한된다. A 도메인에서 저장한 데이터는 B 도메인에서 조회할 수 없다. 이는 데이터의 보안 측면에서 당연하다.
LocalStorage
- 로컬 스토리지는 저장한 데이터를 지우지 않는 이상 영구적으로 보관이 가능하다. (도메인 마다 별도로 로컬 스토리지가 생성된다.)
- 자동 로그인 (영구적으로 저장되어도 상관 없는 데이터들)
SessionStorage
- 브라우저가 열려있는 한 페이지를 Reload해도 계속 유지된다. 하지만 브라우저를 닫으면 삭제된다.
- 은행 로그인, 비로그인 장바구니 (민감한 데이터)
데이터 범위 측면
웹 스토리지는 데이터의 보안측면에서 도메인 단위로 별도 생성된다. 하지만 결정적인 차이가 있다.
LocalStorage는 도메인만 같으면 전역적으로 데이터가 공유되지만,
SessionStorage는 도메인이 같아도 브라우저가 다르면 데이터 공유가 안된다. 탭 브라우징이나 또 다른 브라우저를 실행했을 때, 서로 각각 SeesionStorage가 유지된다.
브라우저 저장소는 쿠키와 비슷하다고 했는데, 쿠키는 무엇인가? 이에 앞서 HTTP 프로토콜의 특징을 알아보자
- 비연결성(Connectionless) : 클라이언트와 서버가 요청과 응답을 한 번 주고받으면 연결을 끊어버리는 특징을 말한다. 클라이언트가 request를 서버로 보내면 서버는 클라이언트가 보낸 request에 맞게 response를 보내고 연결을 끊는다.
- 무상태성(Stateless) : 요청과 응답으로 인해 통신이 끝나면 상태 정보를 유지하지 않는 특징이다.
쿠키 (Cookie)
클라이언트에 저장되는 key와 value로 이루어진 데이터이다. 인증 유효 시간을 설정할 수 있고, 유효 시간이 정해지면 클라이언트가 종료되어도 쿠키가 유지된다. 서버와 요청 응답으로 인해 쿠키가 저장되면 다음 요청은 쿠키에 담긴 정보를 이용해 참조한다.
- 쿠키 동작 방식
- 클라이언트가 로그인 요청
- 서버에서 쿠키 생성 후 클라이언트로 전달
- 클라이언트가 서버로 요청을 보낼 때 쿠키를 전송
- 쿠키를 이용해 유저 인증을 진행
하지만 쿠키에는 치명적인 단점이 있다.
- 4KB의 데이터 저장 제한
- HTTP Request에 암호화 되지 않은 상태로 사용하기 때문에 보안에 취약하다.
사용자 인증에 대한 정보를 모두 클라이언트가 가지고 있게되므로 HTTP 요청을 탈취당할 경우 쿠키 자체를 탈취당해 사용자 정보를 모두 빼앗길 수 있다. 따라서 보안과는 상관이 없는 '오늘 더 이상 보지 않기' 등의 팝업창이 나타나지 않게 하는 경우에 사용된다.
Web Storage 와 Cookie 의 비교
1. 쿠키는 매번 서버로 전송된다.
웹사이트에서 쿠키를 설정하면 이후 모든 웹 요청은 쿠키정보를 포함해 서버로 전송된다. Web Storage는 저장된 데이터가 클라이언트에 존재할 뿐 서버로 전송되지는 않는다. 이는 네트워크 트래픽 비용을 줄여준다.
2. Web Storage는 단순 문자열을 넘어(스크립트) 객체정보를 저장할 수 있다.
문자열 기반 데이터 외에 체계적으로 구조화된 객체를 저장할 수 있다. 이는 개발 편의성을 제공해주는 장점이다. (단, 브라우저의 지원 여부를 확인해봐야한다.)
3. Web Storage는 용량의 제한이 쿠키보다 크다.
쿠키는 개수와 용량에 제한이 있다. 클라이언트에 최대 300개의 쿠키를 저장할 수 있으며, 하나의 사이트(도메인)에서는 최대 20개를 저장할 수 있다. 또한 하나의 쿠키값은 최대 4KB로 제한되어 있다. 그러나 브라우저 저장소는 최대 5MB까지 가능하다.
4. Web Storage는 영구 데이터 저장이 가능하다.
쿠키는 만료일자를 지정하게 되어있어 언젠가 제거된다. 만료일자를 저장하지 않으면 세션쿠키가 된다.
세션쿠키(Session Cookie) : 활성 웹 브라우저 세션이 있는 기간동안 저장된다. 세션쿠키는 일반적으로 웹 브라우저를 닫을 때 삭제된다.
Web Storage 와 쿠키는 모두 클라이언트에 저장한다는 공통점이 있다. 그렇다는 서버에 저장하는 방법은 없을까?
세션 (Session)
쿠키는 방문자의 정보를 방문자의 컴퓨터 메모리에 저장한다. 하지만 세션은 쿠키를 기반으로 하지만, 방문자의 요청에 따른 정보를 방문자 메모리가 아니라, 웹 서버가 세션ID를 만들어 서비스가 돌아가고 있는 서버에 저장한다. 서버에서는 클라이언트를 구별하기 위해 각각의 세션ID를 클라이언트마다 부여하게 되며 클라이언트가 종료되기 전까지 유지한다. 클라이언트에 저장하는 쿠키보다는 보안이 좋다.
- 세션 동작 방식
- 클라이언트가 로그인 요청
- 서버에서는 클라이언트에게 고유한 세션ID를 부여하고 세션 저장소에 저장한 후 클라이언트에게 발급한다.
- 클라이언트는 서버에서 발급받은 세션ID를 쿠키에 저장하게 되고 요청을 보낼 때 마다 쿠키를 보낸다.
- 서버는 쿠키에 담겨있는 세션ID와 세션 저장소에 있는 정보와 대조한 후 데이터를 가져온다.
세션 또한 문제점을 가지고 있다.
- 세션을 이용한 인가 방식은 서버의 메모리에 부담을 준다.
서버는 사용자에게 세션ID를 주고 서버의 메모리에 세션ID를 저장한다. 이때 브라우저는 쿠키에 세션ID를 저장하고, 사용자의 요청에 따라 서버에서 세션ID를 메모리에서 조회하는 방식인데 이는 서버의 메모리에 부담을 준다. 특히 동시에 접속한 사용자가 많을 경우 서버의 메모리가 부족해지고 성능 저하의 주요 원인이 된다. 서버가 재부팅해야하는 상황이 생기면 메모리에 저장되어있던 세션ID가 모두 사라지게 된다. - 세션 하이재킹 공격이 가능하다.
시스템 간 연결이 활성화된 상태, 즉 로그인 된 상태를 가로채는 것을 뜻한다. 그래서 별도의 인증 작업 없이 가로챈 세션으로 통신을 계속할 수 있는데, 이는 세션의 유효시간을 만들어 예방할 수 있다.
Cookie | Session | |
저장위치 | 방문자의 컴퓨터 메모리 | 서비스가 돌아가고 있는 서버 |
보안 | 클라이언트에 저장하기 때문에 세션에 비해 위험하다. | 서버에 저장하기 때문에 쿠키에 비해 안전하다. |
삭제 | 유효기간을 정해서 삭제할 수 있으며, 브라우저가 종료되더라도 저장되어 있을 수 있다. |
만료시간/날짜를 정해서 삭제할 수 있으며, 브라우저 종료시 저장된 데이터가 사라지게 된다. |
따라서 쿠키와 세션을 통한 로그인 인가 방식은 바람직하지 않다.
이런 이유로 부담 없이 인가를 구현하기 위해 고안된 것이 JWT이다.
인증(Authentication) : 유저가 누구인지 확인하는 절차, 회원가입하고 로그인 하는 것
인가(Authorization) : 유저가 요청하는 request를 실행할 수 있는 권한이 있는 유저인가를 확인하는 절차 (로그인 여부 판단)
JWT (JSON Web Token)
JWT는 인증에 필요한 정보들을 암호화시킨 토큰을 의미한다.
세션 방식처럼 토큰 자체를 쿠키에 담아서 보내줄 수 있고 HTTP 헤더에 담아서 보내줄 수도 있다.
이 토큰은 암호화된 3가지 데이터를 이어붙인 것이다.
- Header : 3가지 요소를 암호화할 알고리즘 등과 같은 옵션이 들어간다.
- type : 항상 jwt가 들어간다. (고정)
- alg : 알고리즘의 약자, Verify signature를 만드는데 사용될 알고리즘이 지정된다.
- Payload : 유저의 고유 ID 등 인증에 필요한 정보가 들어간다.
- iss : 토큰 발급자
- sub : 토큰 제목
- aud : 토큰 대상자
- exp : 토큰 만료 시간
- 그 외에 서비스가 사용자에게 이 토큰을 통해 공개하기 원하는 내용(사용자의 닉네임, 서비스상의 레벨, 관리자 여부 등)을 서비스 측에서 원하는 대로 담을 수 있다.
- 이 토큰에 담긴 데이터를 claim이라고 한다. 사용자가 서버에게 요청을 하면 서버는 사용자 정보를 알기 위해 사용자에게 토큰을 받아서 claim 데이터를 읽는다. 이는 서버가 요청마다 일일이 데이터베이스에서 뒤져봐야할 것들이 줄어드는 것이다.
- Verify Signature
(Header + Payload + Secret Key)을 암호화 알고리즘에 넣으면 Verify Signature 값이 된다. Secret Key를 알지 못하면 Verify Signature는 복호화할 수 없다. 서버가 아닌 다른 곳에서 claim을 변경하였다면 이 두 값이 일치하지 않을 것이고, 서버에서 요청을 거부하게 된다. 값이 일치하고 유효기간도 지나지 않았다면 사용자는 인가를 받게 된다.
이 JWT는 세션과 다르게 stateless이다.
Access Token & Refresh Token
JWT 방식에서 토큰은 서버가 아닌 클라이언트에 존재하므로 서버에서 통제할 수 없다. 예를 세션을 이용한 인가 방식에서는 서버의 메모리에서 세션ID를 지워버리면 사용자를 강제 로그아웃 시킬 수 있지만, JWT 방식으로는 서버에서 관리하지 않기 때문에 이러한 기능을 구현하지 못한다. 또한 이 토큰이 외부로 유출되었을 때 서버에서 이 토큰을 무효화할 방법도 없다.
이러한 단점 때문에 다음과 같은 방법이 존재한다.
- 사용자가 로그인하면 서버에서 두 개의 토큰을 발급한다.
- 서버는 클라이언트에게 수명이 짧은 Access 토큰과 수명이 긴 Refresh 토큰을 발급하고 Refresh 토큰의 상응값을 데이터베이스에 저장한다.
- 사용자는 access 토큰의 수명이 다하면 refresh 토큰을 서버에 보낸다.
- 서버는 refresh 토큰을 데이터베이스에서 조회해보고 맞다면 새 access 토큰을 사용자에게 보낸다.
- 이 refresh 토큰이 안전하게 관리된다면 refresh 토큰이 유효할 동안에는 access 토큰이 만료될 때마다 다시 로그인할 필요가 없게 된다.
- 서버에서 사용자를 강제 로그아웃 시키려면 데이터베이스의 refresh 토큰을 삭제하면 된다. 그러면 사용자가 refresh 토큰을 보내도 서버에서 새로운 access 토큰을 보내지 않을 것이다.
JWT의 한계
Access 토큰이 유효한 동안에는 이를 바로 차단할 방법이 없다.
또 외부 공격자가 접근하기 쉬운 위치(HTTP Request header 내부 필드)에 있으며, 정보가 노출 가능될 수 있다. 따라서 저장할 수 있는 정보가 제한적이다.
출처 :
https://hsp0418.tistory.com/120
https://velog.io/@stampid/%EC%BF%A0%ED%82%A4-%EC%84%B8%EC%85%98-%EA%B7%B8%EB%A6%AC%EA%B3%A0-JWT
https://velog.io/@aaronddy/%EC%9D%B8%EC%A6%9DAuthentication%EA%B3%BC-%EC%9D%B8%EA%B0%80Authorization
https://tansfil.tistory.com/59
'코딩 > 정말 나는 잘 알고 있을까?' 카테고리의 다른 글
this가 뭐야? (0) | 2022.08.07 |
---|---|
null, undefined, undeclaered, NaN 이 뭐야? (0) | 2022.08.06 |
절차 지향 프로그래밍 & 객체 지향 프로그래밍이 뭐야? (0) | 2022.08.06 |
JavaScript가 뭐야? (feat. 프로토타입, 싱글 스레드, 비동기적 코딩) (0) | 2022.08.05 |
프로그래밍 언어가 뭐야? (0) | 2022.08.04 |