해당 유저가 로그인 시 실제 등록된 유저인지 인증하게 되고, 인증이 되었다면 해당 세션Id(쿠키) 및 JWT 정보를 헤더에 담아 전달하게 된다.
이후 요청에서 브라우저에 저장된 쿠키 및 Header(JWT) 정보를 넣어서 서버에 원하는 API 요청
header.payload.signature
의 형식으로 3가지의 데이터를 포함 (개미처럼 머리, 가슴, 배).
이 포함된 데이터https://jwt.io/ 에서 간단히 확인가능
{
"alg": "HS256"
"type" "JWT"
}
{
"loggedInAs": "admin"
"iat" 123353111
}
{
"loggedInAs": "admin"
"iat" 123353111
}
// npm i jsonwebtoken
const jwt = require('jsonwebtoken');
// 토큰 생성, payload: { test: true } 시크릿 키: 'my-secret-key' expiresIn: 만료기한
const token = jwt.sign(
{ test: true },
'my-secret-key',
{ expiresIn: 5 });
console.log(token);
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZXN0Ijp0cnVlLCJpYXQiOjE2NDAxNzI3NTN9._Nu27p4dDeGdvjncA_mBFZFEYNxWVeuGdkK2DJzdG1Y
// 복호화
const decoded = jwt.decode(token)
console.log(decoded)
// { test: true, iat: 1640173279 }
// 정상적인 토큰인지 검증
const verify = jwt.verify(token,"my-secret-key")
console.log(verify)
// { test: true, iat: 1640173279 }
// 만약 시크릿키가 정상적이지 않다면 error 발생
// 머리(HEADER).가슴(PAYLOAD).배(VERIFY SIGNATURE) 로 생성이되며
// jwt.io에서 해당 token을 입력해 보면
// 가슴(payload)에 해당 데이터인 {"test": true} 을 담고 있다.
// 누구나 해당 사이트에서 Encoded(복호화)를 통해 데이터를 확인할 수는 있지만
// 변조가 불가능하며
// 배(VERIFY SIGNATURE)에 시크릿키(여기서는 "my-secret-key"를 입력해야
// 해당 데이터가 정상적인 토큰인지 signature verified 할 수 있다.
데이터를 교환하고 관리하는 방식인 쿠키/세션과 달리, JWT는 단순히 데이터를 표현하는 형식
Client -> Server
로그인 요청
Server <-> Database
Verify(검증 성공 or 실패)
Server
세션 생성(Create Session)
Server
세션에 해당 데이터 저장 ( 데이터베이스 or 파일 시스템 or 메모리 )
Server -> Client
{ Cookie: sessionId } 정보를 넣어 클라이언트에 보내줌
( HTTP Only 옵션: 해당 쿠키는 브라우저에 의해서만 읽을 수 있게 됨 )
Client -> Server
이후 브라우저에서 요청을 보낼 때 전달받은 { Cookie: sessionId } 함께 보내줌
Server
존재하는 sessionId or 만료기한을 파악하여 유효하다면 사용자가 누구인지 파악 및 요청 처리
Server -> Client
관련된 데이터를 클라이언트 에 보내줌
🔎 시시각각 변하는 사용자에 대해 세션에 정보를 보관하고 있기 때문에 서버를 확장해 여러 서버에서 동작을 하거나 마이크로 서비스를 하는 경우 한 다양한 서버들이 세션 정보를 확인하기위해 네트워크 요청을 해야함
즉, 클라이언트 요청을 처리하기 위해 내부적으로 여러가지 네트워크 요청을 해야해서 시간이 오래걸리고 분산형 시스템으로 서비스를 잘 디자인 했음에도 세션으로 인해 성능이 좋지 안은 경우가 발생