정보를 비밀리에 전달하거나 인증할 때 주로 사용하는 토큰
Json 객체를 이용
쿠키와 달리 클라이언트에 많은 양의 정보를 담지 않음
세션과 달리 서버에서 상태를 유지하지 않음
stateless
JWT
는 3개의 문자열로 구성되어 있다
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJuYW1lIjoi7ZeI7KSA6riwIn0
.KQcvhAOTFvw1VNcBdijI5Z7BEdr4ozyXrrlrmXkizO0
이건 예시로 가져온 JWT
이다
중간에 .
이 2개 보이는데 이걸로 구분이 된다
맨 앞의 문자열은 Header
이다
//eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
{
"alg": "HS256",
"typ": "JWT"
}
이런식으로 구성된 정보가 들어간다.
type
은 우리가 사용하는 것이 JWT
이므로 JWT
가 들어가야 된다
alg
는 알고리즘을 뜻하는데 signature
부분의 값을 만드는데 사용될 알고리즘을 정해준다
여기서는 HS256
이라는 알고리즘을 지정해준 것을 볼 수 있다
두 번째 문자열은 Payload
(정보)이다
//.eyJuYW1lIjoi7ZeI7KSA6riwIn0
{
"name": "허준기"
}
이런식으로 json
형식으로 여러 정보들이 담겨있다
지금은 내 이름밖에 넣어놓지 않았는데 다른 정보들도 더 넣을 수 있다
Header
의 인코딩 값과 Payload
의 인코딩 값을 합친 후, secret key
로 해쉬
를 해 생성한다
//.KQcvhAOTFvw1VNcBdijI5Z7BEdr4ozyXrrlrmXkizO0
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
"secret key"
)
이런식으로 구성되어 있다
저기에 secret key
라고 해놨는데 내가 해놓은 secret key
는 저게 아니다!
비밀이니까 안보여준다.
아무튼 secret key
를 이용해서 토큰을 만들어준다
위에 한것처럼 토큰을 만들어보고 싶다면
https://jwt.io/
여기서 해보면 된다
이제 구조를 알아봤으니 사용을 해보자
나는 자바에서 사용을 했다
public String createToken(Integer schoolId) {
SecretKey key = Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8));
return Jwts.builder()
.expiration(Date.valueOf(LocalDateTime.now().plusMinutes(expiredTime).toLocalDate()))
.claim("schoolId", schoolId)
.signWith(key)
.compact();
}
이 메서드를 통해서 JWT
를 발행해줬다
이 때 expiredTime
이랑 secretKey
는 위에서 미리 선언을 해놓은 것이다
이 메서드는 학번만 인자로 전달해서 JWT
를 발행한다
현재시간에 expiredTime
을 더해서 유효기간을 정해준다
이제 반대로 JWT
에서 원하는 값을 뽑아와보자
public Integer getSchoolId(String token) {
SecretKey key = Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8));
String schoolId = Jwts.parser()
.verifyWith(key)
.build()
.parseSignedClaims(token)
.getPayload()
.get("schoolId").toString();
return Integer.parseInt(schoolId);
}
이렇게 JWT
에서 schoolId
를 뽑아올 수 있다
나는 이 메서드로 존재하는 사용자인지 비교를 해줬다
지금까지 사용방법을 알아봤고 이제 주의점에 대해서 알아보자
위에서 말한대로 Header
부분에 알고리즘을 지정해줄 수 있다.
이 때 공격자가 alg
부분에 none
이라고 넣어서 요청을 보내면 뚫리는 경우가 있다고 한다
→ 최신 라이브러리들을 잘 쓰면 된다고 한다
JWT
는 디코딩
이 굉장히 쉽기 때문에 민감한 정보를 넣어서 저장하면 안된다
→ 꼭 필요한 정보들만 넣어서 전달하자(민감한 정보 말고)
secretKey
를 설정해줄 때 간단하고 유추 가능한 문자열로 적을 경우 때려 맞힐 가능성이 있으니 주의해라
누가 JWT
를 탈취할 경우가 생길 수도 있다
하지만 JWT
는 사용 정지가 불가능하다
그래서 해당 JWT
의 유효기간이 지나기 전까지 탈취자는 마음대로 입장을 할 수 있다
JWT
를 사용하는 의미가 없어짐