본문 바로가기
IT 이야기/Java

[JWT] Java Web Token

by Dblog 2021. 11. 2.
728x90

Spring security를 공부하다보면 JWT를 만나게 됩니다.
보안 인증을 JWT 토큰으로 지원할 수 있고 생각보다 높은 성능의 보안을 지원합니다. 

https://docs.spring.io/spring-security/site/docs/current/reference/html5/

 

Spring Security Reference

In Spring Security 3.0, the codebase was sub-divided into separate jars which more clearly separate different functionality areas and third-party dependencies. If you use Maven to build your project, these are the modules you should add to your pom.xml. Ev

docs.spring.io

 


JWT의 구조는 Header, payload, signature로 이루어져있으며 각 항목의 구분자는 . 로 구분됩니다.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwicGFzc3dvcmQiOiIxQTJzc2FBQSEhQCIsImlhdCI6MTUxNjIzOTAyMn0.K6Tib_A8OO_9bF7d6pnyvWNWuzI05EG-3lin-4M1-eQ

 

Header

Header는 알고리즘, type 으로 구성되어 있으며 key, value형태로 되어있습니다. 

{
  "alg": "HS256",
  "typ": "JWT"
}

Json을 minify하고 base64로 hashing하면 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 값을 얻을 수 있습니다.
※Json을 minify하지 않으면 공백, 줄바꿈 문자들이 같이 encode 되기 때문에 원하는 값을 얻을 수 없습니다.

 

Payload

Payload 영역에는 JWT토큰에 담고싶은 내용을 적는 부분으로 보통 email. id 값을 작성하게 되며 exp(만료시간), iat(발행일자)값을 함께 동봉합니다.

{
  "sub": "1234567890",
  "name": "John Doe",
  "password": "1A2ssaAA!!@",
  "iat": 1516239022
}

payload를 encode하면 아래와 같은 값이 얻어집니다.

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwicGFzc3dvcmQiOiIxQTJzc2FBQSEhQCIsImlhdCI6MTUxNjIzOTAyMn0=

그런에 우리가 가지고 있는값인
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwicGFzc3dvcmQiOiIxQTJzc2FBQSEhQCIsImlhdCI6MTUxNjIzOTAyMn0



eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwicGFzc3dvcmQiOiIxQTJzc2FBQSEhQCIsImlhdCI6MTUxNjIzOTAyMn0=
는 비교했을때 살짝 차이가 있습니다.

맨 뒤에 =이 사라지는 것인데 이것도 규칙이 있습니다.

간단하게는 URL에 safe 하지 않은 문자인 +,/,= 를 URL safe하게 변경해 주는 것 입니다.

base64 base64url
+ -  (minus)
/ _  (under line)
= none

 

base64, base64 URL 자세히 보기

더보기
  • base64 색인표
문자 문자 문자 문자
0 A 16 Q 32 g 48 w
1 B 17 R 33 h 49 x
2 C 18 S 34 i 50 y
3 D 19 T 35 j 51 z
4 E 20 U 36 k 52 0
5 F 21 V 37 l 53 1
6 G 22 W 38 m 54 2
7 H 23 X 39 n 55 3
8 I 24 Y 40 o 56 4
9 J 25 Z 41 p 57 5
10 K 26 a 42 q 58 6
11 L 27 b 43 r 59 7
12 M 28 c 44 s 60 8
13 N 29 d 45 t 61 9
14 O 30 e 46 u 62 +
15 P 31 f 47 v 63 /
  • base64 url 색인표
문자 문자 문자 문자
0 A 16 Q 32 g 48 w
1 B 17 R 33 h 49 x
2 C 18 S 34 i 50 y
3 D 19 T 35 j 51 z
4 E 20 U 36 k 52 0
5 F 21 V 37 l 53 1
6 G 22 W 38 m 54 2
7 H 23 X 39 n 55 3
8 I 24 Y 40 o 56 4
9 J 25 Z 41 p 57 5
10 K 26 a 42 q 58 6
11 L 27 b 43 r 59 7
12 M 28 c 44 s 60 8
13 N 29 d 45 t 61 9
14 O 30 e 46 u 62 -
15 P 31 f 47 v 63 _

 

위의 내용들을 하나하나 처리하고 encoding 한 결과를 보면 처음 생성했던 jwt 토큰과 하나하나 뜯어가며 만들어낸 jwt 토큰의 값은 아래와 같이 동일합니다.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwicGFzc3dvcmQiOiIxQTJzc2FBQSEhQCIsImlhdCI6MTUxNjIzOTAyMn0

그런데 마지막 부분인 K6Tib_A8OO_9bF7d6pnyvWNWuzI05EG-3lin-4M1-eQ signature 부분은 아직 얻어내지 못했습니다.

이 signature 부분은 지금까지 encoding한 값인 algo + payload의 encoding 값과 user secret 값을 함께 sha256으로 한번 더 해시를 하면 얻을 수 있습니다.

signature부분은 알고리즘이나 payload의 작은 한부분만 변경되어도 값이 크게 달라지기 때문에 JWT가 보안성이 어느정도 좋다고 할 수 있는 이유입니다.


그러나 JWT를 잘못 이해해서 정확하게 사용하지 못한다면 오히려 보안이 약해질 수도 있습니다. 

아래 사진은 JWT토큰을 decode한 내용입니다. 만약 사진처럼 payload영역에 password를 입력했다면 토큰만 서버에 요청해서 받은뒤 디코딩해서 비밀번호를 획득할 수 있게 됩니다.

적혀있는 JWT코드를 그대로 가져가서 decode하면 똑같은 결과를 얻을수 있을것입니다.

 

728x90

댓글