Skip to content

[BE] JWT

xrabcde edited this page Aug 1, 2021 · 1 revision

JWT

  • JWT의 기본적인 개념(구조, 생성과정)
  • 프로젝트에서 토큰을 다루기 위해 만든 JwtUtils의 API 설명

JWT 구조와 생성 과정

인코딩되기 전의 형태

Jason Web Token은 JSON로 쓰여진 2가지 부분(Header, Payload)과 암호화된 String(Signature)을 연결해서 만들어진다. 당연하지만 Header와 Payload는 JSON 형식이므로 key-value 형태로 이루어져있다.

Header

Json 형식으로 이루어져있다. 각 key에는 다음과 같은 정보가 들어간다.

  • typ: 토큰의 타입을 담는다. e.g., 'jwt'
  • alg: JWT의 마지막 부분 Signature를 생성하기 위해 어떤 알고리즘을 사용하는지 적는다. e.g., 'hs-256'

Payload

Json 형식으로 이루어져있다. 기본적으로 원하는 값을 넣어서 사용하는데에 주로 쓰인다.

다만 관습적으로 사용되는 키들이 있다.

  • sub: 'subject'를 뜻한다. 토큰이 누구에게 발급되었는지를 의미한다. e.g., 'user1234', '12'(PK), 'pobi@woowa.com' 등...
  • iat: 'issuedAt'을 뜻한다. 언제 발급되었는지를 뜻한다. 형식은 유닉스 시간이다. e.g., 1569302116...
  • exp: 'expiredAt'을 뜻한다. 언제 만료되는 지를 뜻한다. 마찬가지로 유닉스 시간을 사용한다.

Signature

다음의 값들을 Header의 alg에 명시된 알고리즘으로 해싱해서 생성한다.

  • Header를 Base64로 인코딩한 값
  • Payload를 Base64로 인코딩한 값
  • 임의로 설정한 암호화키(SecretKey, 위 이미지 상으로는 secret_salt에 해당한다), 암호화하기 위한 키로 사용된다.

대략적인 수도코드

암호화_알고리즘(
    base64Encode(Header) + "." + base64Encode(Payload)
    ,
    secretKey
)

인코딩 후 형태

생성 과정

  • 위 과정에 의해 만들어진 각각의 Header, Payload, Signature를 각각 Base64로 인코딩한다.
  • 각 파트를 "."으로 이어붙인다.

수도 코드

Base64(Header) + "." + Base64(Payload) + "." + Base64(Signature)

구조에 따른 성질

JWT는 그 구조와 생성과정으로 인해, 마음대로 읽을 수는 있지만 수정은 불가능한 특성을 가진다.

1. 클라이언트는 마음대로 Header와 Payload를 읽을 수 있다.

Base64로 인코딩했을 뿐 암호화되어 있는 것은 아니기 때문에 언제든 디코딩해서 이를 읽어볼 수 있다.

2. Signature는 읽을 수 없다.

서버에서만 소유한 비밀키를 통해 암호화되어 있기 때문에 Signature는 읽어들일 수 없다.

3. 클라이언트는 Header 혹은 Payload를 조작한 JWT로 인증할 수 없다.

Signature는 Header와 Payload를 해싱의 값으로 이용하기 때문에, 이 둘의 값이 바뀌면 Signature도 바뀌어야 한다.

서버는 클라이언트로부터 받은 Header와 Payload를 다시 해싱 및 암호화한 후 Signature와 일치하는지를 검사하기 때문에, 클라이언트가 이 값을 바꾸었다면 Signature 인증에 실패할 수 밖에 없다.


JwtUtils API

JwtUtils.createToken(Map<String, Object> payload);

  • Map의 값들을 이용해 payload를 JSON 형태로 생성합니다.
  • value는 Object 타입으로, 라이브러리의 내부 직렬화 로직에 의해 직렬화되어 사용됩니다.
  • payload에 설정된 값들 이외에 iat(issuedAt), exp(expiredAt)을 설정합니다.
  • 만료기한을 뜻하는 exp값은 설정 파일(appliction.properties)에 설정된 유효기간에 의해 설정됩니다.

JwtUtils.payloadBuilder();

  • JwtUtils의 내부 클래스 PayloadBuilder를 생성합니다.
  • 일부 관습적인 payload 값들을 메소드명을 통해 쉽게 설정할 수 있도록 도와줍니다.
  • 예컨대, setSubject(String) 메소드는 매개변수로 받은 문자열을 payload의 sub 키에 value로 설정합니다.
  • 마지막으로 build()를 하면 Map<String, Object>

JwtUtils.validateToken(String token);

Clone this wiki locally