-
Notifications
You must be signed in to change notification settings - Fork 20
[BE] JWT
xrabcde edited this page Aug 1, 2021
·
1 revision
- JWT의 기본적인 개념(구조, 생성과정)
- 프로젝트에서 토큰을 다루기 위해 만든 JwtUtils의 API 설명
Jason Web Token은 JSON로 쓰여진 2가지 부분(Header, Payload)과 암호화된 String(Signature)을 연결해서 만들어진다. 당연하지만 Header와 Payload는 JSON 형식이므로 key-value 형태로 이루어져있다.
Json 형식으로 이루어져있다. 각 key에는 다음과 같은 정보가 들어간다.
-
typ
: 토큰의 타입을 담는다. e.g., 'jwt' -
alg
: JWT의 마지막 부분Signature
를 생성하기 위해 어떤 알고리즘을 사용하는지 적는다. e.g., 'hs-256'
Json 형식으로 이루어져있다. 기본적으로 원하는 값을 넣어서 사용하는데에 주로 쓰인다.
다만 관습적으로 사용되는 키들이 있다.
-
sub
: 'subject'를 뜻한다. 토큰이 누구에게 발급되었는지를 의미한다. e.g., 'user1234', '12'(PK), 'pobi@woowa.com' 등... -
iat
: 'issuedAt'을 뜻한다. 언제 발급되었는지를 뜻한다. 형식은 유닉스 시간이다. e.g., 1569302116... -
exp
: 'expiredAt'을 뜻한다. 언제 만료되는 지를 뜻한다. 마찬가지로 유닉스 시간을 사용한다.
다음의 값들을 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는 그 구조와 생성과정으로 인해, 마음대로 읽을 수는 있지만 수정은 불가능한 특성을 가진다.
Base64로 인코딩했을 뿐 암호화되어 있는 것은 아니기 때문에 언제든 디코딩해서 이를 읽어볼 수 있다.
서버에서만 소유한 비밀키를 통해 암호화되어 있기 때문에 Signature는 읽어들일 수 없다.
Signature는 Header와 Payload를 해싱의 값으로 이용하기 때문에, 이 둘의 값이 바뀌면 Signature도 바뀌어야 한다.
서버는 클라이언트로부터 받은 Header와 Payload를 다시 해싱 및 암호화한 후 Signature와 일치하는지를 검사하기 때문에, 클라이언트가 이 값을 바꾸었다면 Signature 인증에 실패할 수 밖에 없다.
- Map의 값들을 이용해 payload를 JSON 형태로 생성합니다.
- value는 Object 타입으로, 라이브러리의 내부 직렬화 로직에 의해 직렬화되어 사용됩니다.
- payload에 설정된 값들 이외에
iat
(issuedAt),exp
(expiredAt)을 설정합니다. - 만료기한을 뜻하는
exp
값은 설정 파일(appliction.properties)에 설정된 유효기간에 의해 설정됩니다.
-
JwtUtils
의 내부 클래스PayloadBuilder
를 생성합니다. - 일부 관습적인 payload 값들을 메소드명을 통해 쉽게 설정할 수 있도록 도와줍니다.
- 예컨대,
setSubject(String)
메소드는 매개변수로 받은 문자열을 payload의sub
키에 value로 설정합니다. - 마지막으로 build()를 하면 Map<String, Object>