JWT(JSON Web Token) 란?[ yoonbumtae (BGSMM)]
JWT(JSON Web Token)
는 JSON 객체를 사용하여 가볍고 자가수용적인 (self-contained) 방식으로 정보를 안전성 있게 전달해주기 위한 토큰이다.
JWT
는 RFC7519 표준으로,
JSON 객체 형태로 당사자 간 정보를 안전하게 전송하기 위한 소형의 자체 포함 형식으로 정의된다.
당사자간에 전송할 Claim을 나타내는 URL에 안전(url-safe)한 압축 수단
JWT
의 구조는 Header
, Payload
, Signature
세 가지를 포함하는 구조를 준수해야한다.
[Base64Encoded(HEADER)].
[Base64Encoded(PAYLOAD)].
[Encoded(SIGNATURE)]
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJpZCI6ImdpbGxvZyIsIm5hbWUiOiJHaWxsb2ciLCJpYXQiOjE1MTYyMzkwMjJ9.
_OqpMXmKk6ajncTx5zCcC4ZxQwoVJZKep0Hh-Aw5YRM
Header
는 일반적으로 Token Type(typ)과,
사용중인 서명 Algorithm(alg)의 두 부분으로 구성된다.
{
"alg": "HS256",
"typ": "JWT"
}
Payload
는 Token에 담을 정보를 나타내며 Claim
들을 포함한다.
Claim
은 Payload
한 부분 들을 의미하고,
name
, value
한 쌍의 구조로 구성된다.
Claim
에는 Reserved(등록된)
, Public(공개)
, Private(비공개)
세 가지 유형이 있다.
Reserved Claim
은 유용하고 상호 운용 가능한 제공을 위해 권장되는 미리 정의된 Claim 집합이다.
예시는 아래 표와 같다.
Claim | 약어 | 의미 |
---|---|---|
Issuer | iss | 발행자 |
Expiration | exp | 만료시간 |
Subject | sub | 주제 |
Audience | aud | 대상자 |
{
"iss": "gillog",
"exp": "1485270000000",
"aud": "user",
"sub": "study"
}
Public Claim
들은 충돌이 방지된 (Collision-Resistant) 이름을 가지고 있어야 한다.
충돌 방지를 위해 Claim 이름을 URI 형식으로 짓는다.
Private Claim
은 Client-Server 간의 미리 정해져 사용되는 Claim 이름들이다.
Public Claim
과 달리 이름이 중복되어 충돌이 될 수 있어 유의해야 한다.
Signature
는 JWT의 무결성을 보증하는데 사용하고,
Private Key
로 서명된 토큰의 경우 JWT 발신자가 누구인지 확인할 수도 있다.
Signature
를 만들기 위해선 Encoding된 Header
,
Encoding된Payload
와 Secret Key
,
Header
에서 지정된 암호화 Algoritm
이 있어야 한다.
1.Browser
는 로그인과정에서 회원정보를 Server
에 제공.
2.Server
는 회원 정보와 Secret Key
를 이용, JWT
를 생성.
3.Server
는 생성한 JWT
를 Browser
에게 전송.
4.Browser
는 해당 회원에 대한 정보가 필요할때 발급받은 JWT
를 Header에 넣어 Server
에게 요청.
5.Server
는 Secret Key
로 요청 JWT의 Signature
를 검증한 후 해당 정보를 Browser
에게 제공.
JWT의 장점으로는 수많은 프로그래밍 언어에서 지원되며,
단순 JSON 구조로 그 자체가 모든 정보를 포함하는 자가수용적(Self-Contained) 특성을 지닌다.
다른 환경과 종속되지 않는 독립적 구조, 만료 기간이 자체 내장
Secret Key
를 통해 Server측에서 쉽게 디버깅 및 관리할 수 있고,
수평 스케일링에 용이하다.
또한 HTTP Request
의 Header
또는 URL의 Parameter
로 쉽게 전송될 수 있다.
REST Service로 제공 가능, 트래픽 부담 저하
사용자 인증에 필요한 모든 정보가 토큰 자체에 포함하기 때문에,
별도의 인증 저장소가 필요없다.
따라서 분산 마이크로 서비스 환경
에서,
중앙 집중식 인증 서버
와 데이터베이스
에 의존하지 않는,
쉬운 인증 및 인가 방법을 제공한다.
JWT
는 Client 측에 저장되어 있어, Server DB에서 사용자 정보가 변경되었더라도 Token에 직접 적용할 수 없다.
JWT는 크기가 작지만 만약 Payload의 Claim
이 계속 추가되면,
Token
이 길어질 수 있다.
이는 Staless Application
에서 Token
이 항상 Request
와 함께 전송되기때문에,
데이터 트래픽
크기에 영향을 끼칠 수 있다.
Java에서 jjwt
라는 Library로 쉽게 사용해볼 수 있다.
jjwt
는 JWT
생성 및 파싱, 검증을 위한 Library이다.
아래 Dependency
를 Maven pom.xml에 추가하여 Libarary를 설치해보자.
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
아래 예제 Class 처럼 간단하게 JWT Token을 생성 및 파싱, 검증할 수 있다.
jjwt 0.1x.0 버전대 이후 Deprecated 된 Method들이 많으니 참고만 하자
public class AuthJWT {
private final String secretKey = "Gil11ogG2200";
public static void main(String[] args) throws UnsupportedEncodingException {
AuthJWT authJWT = new AuthJWT();
String jwt = authJWT.createToken();
Map<String, Object> claimMap = authJWT.verifyJWT(jwt);
// 토큰 만료 or 검증 실패 시 null
System.out.println(claimMap);
}
public String createToken() {
//Header 설정
Map<String, Object> headers = new HashMap<>();
headers.put("alg", "HS256");
headers.put("typ", "JWT");
//payload 설정
Map<String, Object> payloads = new HashMap<>();
payloads.put("iss", "gillog");
payloads.put("aud", "all");
payloads.put("data", "Gillog JWT");
Long expiredTime = 1000 * 60L * 60L * 2L;
Date expDate = new Date();
expDate.setTime(expDate.getTime() + expiredTime);
return Jwts.builder()
.setHeader(headers) // Headers 설정
.setClaims(payloads) // Claims 설정
.setSubject("study") // 토큰 용도
.setExpiration(expDate) // 토큰 만료 시간 설정
.signWith(SignatureAlgorithm.HS256, secretKey.getBytes()) // HS256과 Key로 Sign
.compact(); // 토큰 생성
}
public Map<String, Object> verifyJWT(String jwt) throws UnsupportedEncodingException {
Map<String, Object> claimMap = null;
try {
Claims claims = Jwts.parserBuilder()
.setSigningKey(secretKey.getBytes()) // Secreat Key로 Signature 설정
.build()
.parseClaimsJws(jwt) // 파싱 실패 시 에러 발생
.getBody();
claimMap = claims;
// Claim 사용 법 일반 Map 형태 처럼 사용
Date expiration = claims.get("exp", Date.class);
String data = claims.get("iss", String.class);
} catch (ExpiredJwtException e) { // 토큰 만료
...
} catch (Exception e) { // 그 외 에러
...
}
return claimMap;
}
}
JWT is defined as a compact and self-contained format using JSON objects to securely transmit information between parties, following the RFC7519 standard.
It provides a means of securely transmitting claims representing the information between parties in a URL-safe compact format. pge outage map
감사합니다~