요약
- JWT(JSON Web Token): 클라이언트(사용자)와 서버 간에 정보를 JSON 개체로 안전하게 전송하기 위한 개방형 표준(RFC 7519)
- JWT을 이용한 인증 과정: 사용자 측에서 사용자의 정보를 관리하는 토큰 기반 인증 메커니즘
- JWT의 3가지 구성 요소. 각 구성 요소들은 dot(.)으로 구분
- Header: Signature을 만드는데 사용한 알고리즘, Token의 타입 정보
- Payload: 실질적으로 전달해야 하는 정보(각각 Claim)
- Signature: (Header의 인코딩된 내용+Payload의 인코딩된 내용)을 Secret Key와 알고리즘으로 암호화된 JWT의 서명 부분
클라이언트(사용자)와 서버 간에 정보를 JSON 개체로 안전하게 전송하기 위한 개방형 표준(RFC 7519)
특징
구성
전자 서명이 되어 있다는 점
이 중요. 목적
데이터의 신뢰성을 보장
하는 것.HTTPS
를 사용하는 것이 좋다.인증과정
JWT의 3대 구성 요소 : Header, Payload, Signature
Header의 구성요소 | 설명 |
---|---|
alg | Signature을 만드는데 사용한 알고리즘 정보 |
typ | Token의 타입 |
예)
// Header
{
"alg" : "HS256", // 알고리즘: HS256
"typ" : "JWT" // Token 타입: JWT
}
Claim의 종류 | 설명 |
---|---|
Registered Claims | JWT 표준으로 지정된 Claim |
Public Claims | JWT를 사용하는 사람들이 공개적으로 정의하여 사용하는 Claim |
기 등록된 Claims와 충돌 방지위해 IANA JSON Web Token 레지스트를 참고하거나 UUID, OID, 도메인 이름 등을 사용 | |
Private Claims | Public Claims과 달리 오직 사용자와 서버 사이에서만 합의하여 사용하는 Claim |
Registered Claims의 종류
- 무조건 전부 사용하는게 아니라 상황에 맞게 적절히 사용
- iss: 토큰 발급자,
- sub: 토큰 제목,
- aud: 토큰 대상자,
- exp: 토큰 만료시간,
- iat: 토큰 발급 시간,
- nbf: 토큰 활성화 시간,
- jti: JWT의 고유 식별자
예)
{
"exp": "1245678900", //Registered Claims
"https://velopert.com/jwt_claims/is_admin": true, //Public Claims
"user_id" : 12345123 //Private Claims
}
암호화 방식
: 전달 받은 토큰의 Header와 Payload를 서버의 Secret Key를 이용.
JWT 신뢰성 확인
: 해당 값이 전달 받은 Signature와 같은지 비교.
: 신뢰할 수 없는 토큰은? 👉 서버에서 관리하는 Secret Key가 아닌 다른 Key로 발급한 JWT. Signature가 달라지므로!
예)
HS256(HMAC SHA256) 알고리즘으로 암호화된 Signature
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
JWT에서 암호화하는 부분은 시그니처
just.verify()메소드 하나로 다 열린다.
secrete_key는 gitignore에 저장해주어야 한다!
세션의 단점이 스케일아웃 시 관리가 어렵다. 서버끼리 데이터를 공유하는데 왜 관리가 어려울까요?
👉 컴퓨터서버A에서 서비스 중. 300명 한계인데 15000명 접속자 발생!
-> 해결: 컴퓨터 사양을 늘리거(up)나 여러대를 늘리거나(out)
-> 인터넷을 통해 들어와서 로드밸런싱:
-> 세션을 쓴다는 건 서버에서 세션id를 관리한다는 것
컴퓨터a에서 세션 열려있었는데 로드밸런싱으로 컴퓨터b에 들어가면 세션id 달라서..
->> 해결책: 인메모리 데이터베이스 모든 세션 정보를 통으로 기억하는 데이터베이스를 별도로 쓴다.api로 하게되면 한쪽 컴퓨터에 몰리게될 경우 문제가 될 수 있음
그래서 토큰을 사용하면 그럴 일이 없어 스케일아웃이 관리 편하다
세션 자체는 휘발성이다(메모리에 저장) expired
브라우저 단에서 체크,분석할 수 있다, 어떤 활동을 했는지도 데이터베이스에 저장
jwt payload에서 registered claims에서
iat는 발급시간은 발급할때마다 다를 거라 자동으로 생성함. 다른 언어(파이썬?자바?)은 그렇지 않을 수도 있다
토큰 만료시간이 없으면? 누군가 토큰을 탈취했을 때 영원히 사용할 수 있게되므로 만료시간이 필요하다
이벤트를 만들 때 몇명이 들어올지 예측하기 어렵다
1만명 유추했더니 12만명이 들어왔다? 어쩔 수 없음..
예) 질병관리청 코로나 사이트
언제 스케일 아웃할까? 인프라 세팅을 해두면 자동으로 스케일 아웃한다
2차 프로젝트 때 docker를 배우게 되는데 disk를 나눈게 아니라 내os위에 다른 os를 띄우는 가상화(=무겁다)
경량화된 버전에 가상화할 수 있는 컨테이너-> 데브옵스 직군의 업무(쿠버네티스 등)
상당한 공수와 기술자가 들어가는데...
지금 쿠버네티스를 배우는 건 추천하지 않음.(나중에~) 쿼리 최적화, 튜닝을 먼저
위코드의 저 자료는 누가 어떻게 ?
공식문서를 봐야 한다! 꼭 보도록 하자!
npm bcrypt
검색어: 'to hash a password', 'hashSync()'
bcrypt.hash()라는 메소드 자체가 프로미스이고 비동기로 동작한다
-> await는 async()안에서만 쓸 수 있다 => 그래서 함수를 별도 선언하면(위코드에 답이 있음)
-> 사고 훈련을 위해 공식문서를 보고 해결하는 방식을 찾아보자
해시값이었으면 3초면 털릴 것을
bcrypt로 비교해서 90일 정도 지나면 털릴 준비가 됐다
그래서 90일 지나면 비밀번호 바꾸라는 경고가 뜨는 것!
const jwt = require("jsonwebtoken");
토큰을 저장하려면 어디에??
로컬스토리지에 저장한다? 쿠키로 보낸다?
세션에 대한 정보를 가지고 -> 무겁다
토큰을 발급한 순간부터 백엔드의 손에서 벗어난다
토큰은 클라이언트가 저장하고 사용한다