JWT(JSON Web Token) ์ธ์ฆ๋ฐฉ์‹๊ณผ ๋ณด์•ˆํ…Œ์ŠคํŒ…, ์ทจ์•ฝ์  ๋ถ„์„

๐Ÿšง JWT ๊ด€๋ จ ํ…Œ์ŠคํŒ…, ๋ณด์•ˆ ๋‚ด์šฉ์€ ์ œ ๋ธ”๋กœ๊ทธ ๋‚ด Cullinan ํŽ˜์ด์ง€์—์„œ ๊ด€๋ฆฌ์ค‘์ž…๋‹ˆ๋‹ค. Cullinan > JWT ํ•ญ๋ชฉ์„ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

์š”์ฆ˜ ์ธ์ฆ ๊ด€๋ จํ•ด์„œ OAuth๊ฐ€ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋ฉด์„œ ์ž์—ฐ์Šค๋ ˆ JWT์— ๋Œ€ํ•œ ์ด์•ผ๊ธฐ๋„ ๋งŽ์•„์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๋‹ค๋ณด๋‹ˆ ๊ฐœ๋…๋งŒ ์•Œ๊ณ ์žˆ๋˜ JWT์— ๋Œ€ํ•ด ๊ณต๋ถ€๋„ ๋˜๊ณ  ๋ณด์•ˆ์ ์ธ ๋ฌธ์ œ์ ์ด ์žˆ์„๊นŒ ์ƒ๊ฐํ•˜๋Š” ๊ณ„๊ธฐ๊ฐ€ ๋˜์–ด ๊ธ€ ์ž‘์„ฑํ•ด๋ด…๋‹ˆ๋‹ค.

JWT๋ž€?

์ด๋ฆ„ ๊ทธ๋Œ€๋กœ JSON์„ ์ด์šฉํ•œ Web Token ์ž…๋‹ˆ๋‹ค. ์ฃผ๋กœ ์„œ๋น„์Šค์— ๋Œ€ํ•œ ์ธ์ฆ์ด๋‚˜ CSRF ํ† ํฐ๋“ฑ์— ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๊ฒ ์ง€์š”. ์ด๋Ÿฐ JWT๋Š” Base64(Header) + Base64(Payload) + Base64(Signature) ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

ํฌ๊ฒŒ ํ—ค๋”์™€ ํŽ˜์ด๋กœ๋“œ๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ฐ๊ฐ ํ† ํฐ์— ๋Œ€ํ•œ ํฐ ์ •๋ณด์™€ ์‹ค์ œ ๋ฐ์ดํ„ฐ๋กœ ๊ตฌ์„ฑ์ด ๋ฉ๋‹ˆ๋‹ค.

  • JWT์—์„œ ํ† ํฐ์€ ํ—ค๋”์™€ Payload๋กœ ๋‚˜๋ˆ ์ง
  • Header: ์•”ํ˜ธํ™” ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฐ Type์„ ์˜๋ฏธํ•จ
1
2
3
4
{
  "alg":"HS256",
  "typ":"JWT"
}
  • Payload : ์ „์†กํ•  ๋‚ด์šฉ
1
2
3
4
5
{
  "test":0000001,
  "User":"TestUser1",
  "auth":"nomal_user"
}

ํ—ค๋” ๋‚ด์šฉ ์ค‘ alg๋Š” ๋ณด์•ˆ ์•Œ๊ณ ๋ฆฌ์ฆ˜, typ๋Š” type์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. alg๋Š” HS256 ์™ธ ๋‹ค์ˆ˜์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์ง€์ •ํ•œ ๋ฐ์ดํ„ฐ๋Š” ์ธ์ฝ”๋”ฉ ๊ณผ์ •์„ ๊ฑฐ์ณ ์•„๋ž˜์™€ ๊ฐ™์€ Token์œผ๋กœ ๋ณ€ํ™˜๋˜์–ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXJhbTEiOjgwODB9.wNDKI_bZi5E5uWFwQ72QbMUEsn0_mlyT1F2y_0xWSKA

  • Header: red
  • Payload: Blue
  • Signature: Yellow

JWT ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ์„ธํŒ…

์ €๋Š” ์ฃผ๋กœ ๋ฃจ๋น„์™€ C๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์—.. Ruby ๊ธฐ์ค€์œผ๋กœ ์ž‘์„ฑํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. (๋ฌผ๋ก  ๋‹ค๋ฅธ์–ธ์–ด๋„ ๋ณ„ ์ฐจ์ด ์—†์Šต๋‹ˆ๋‹ค =_=)

์ธ์ฆ์€ ํ•ญ์ƒ ํ’€์–ด๋ณด๋Š”๊ฒŒ ๊ฐ€์žฅ ์ข‹์€๋ฐฉ๋ฒ•์ด๋ผ ์ƒ๊ฐ๋ฉ๋‹ˆ๋‹ค.(ํ’€์–ด์ง„๋‹ค๋ฉด..) ํ† ํฐ ์ž์ฒด์—๋Š” ๋ณต์žกํ•œ ๊ทœ์น™์€ ์—†์–ด ์ƒ๊ฐ๋ณด๋‹ค ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ํ’€์ด๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

Generate JWT

1
2
3
4
hmac_secret = 'no'
payload = {:param1 => 8080}
token = JWT.encode payload, hmac_secret, 'HS256'    #encode(payload,key,algorithm)
puts "Encode Token: ", token

์œ„ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด hmac_secret ๋Š” key๋ฅผ ์˜๋ฏธํ•˜๋ฉฐ payload์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ•ด๋‹น ํ‚ค๋ฅผ ์ด์šฉํ•ด HS256์œผ๋กœ Encoding ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ฒฐ๊ณผ๊ฐ’์€ ์•„๋ž˜์™€ ๊ฐ™์ด JWT Token ํ˜•ํƒœ๋กœ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

1
2
Encode Token: 
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXJhbTEiOjgwODB9.wNDKI_bZi5E5uWFwQ72QbMUEsn0_mlyT1F2y_0xWSKA

Decode JWT

1
2
3
4
5
6
require 'jwt'
hmac_secret = 'no'
payload = {:param1 => 8080}
token = JWT.encode payload, hmac_secret, 'HS256'    #encode(payload,key,algorithm)
puts "Encode Token: ", token
puts "Decode Token: ", JWT.decode(token,"no")   #decode(token,Key)

์•„๊นŒ ๋งŒ๋“ค์–ด์ง„ ๋ถ€๋ถ„์„ ํฌํ•จํ•˜์—ฌ ๋‹ค์‹œ ๊ทธ Key๋ฅผ ๊ฐ€์ง€๊ณ  ๋ณต์›ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•˜์ฃ ?

1
2
3
4
5
6
ruby jwtencode.rb
Encode Token: 
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXJhbTEiOjgwODB9.wNDKI_bZi5E5uWFwQ72QbMUEsn0_mlyT1F2y_0xWSKA
Decode Token: 
{"param1"=>8080}
{"typ"=>"JWT", "alg"=>"HS256"}

์ฝ”๋“œ๋กœ๋Š” ์ด๋ ‡๊ฒŒ ํ‘œํ˜„ํ•˜์ง€๋งŒ ์‚ฌ์‹ค ๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ํ’€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. JWT๋Š” ๊ฐ ๊ตฌ๊ฐ„๋ณ„๋กœ Base64๋กœ ์ธ์ฝ”๋”ฉ๋˜๊ธฐ ๋•Œ๋ฌธ์— ํ•ด๋‹น ๋ถ€๋ถ„ ๊ธ์–ด์„œ ๋ณด์‹œ๋ฉด ๋ฐ”๋กœ ํ™•์ธ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

Header: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.

  • {“typ”:“JWT”,“alg”:“HS256”} Payload: eyJwYXJhbTEiOjgwODB9.
  • {“param1”:8080} Signature: wNDKI_bZi5E5uWFwQ72QbMUEsn0_mlyT1F2y_0xWSKA

JWT ์–ด๋–ค ๋ณด์•ˆ์ ์ธ ๋ฌธ์ œ์ ๋“ค์ด ์žˆ์„๊นŒ?

์ด๋Ÿฐ ์ธ์ฆ ํ™˜๊ฒฝ์—์„  ์–ด๋–ค ๋ฌธ์ œ๋“ค์ด ์žˆ์„์ง€ ๊ณ ๋ฏผ์„ ์ข€ ํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ์„ ๊ฒƒ์ด๊ณ , JWT ์ž์ฒด์ ์ธ ๋ฌธ์ œ๋„ ์žˆ์„๊ฒ๋‹ˆ๋‹ค.

ํ† ํฐ ๋‚ด ์ค‘์š”ํ•œ ์ •๋ณด ๋…ธ์ถœ

์ผ๋‹จ ๊ฐ€์žฅ ํ”ํ•œ ๊ฒฝ์šฐ๋Š” ์ด ํ† ํฐ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ๋ฐ์ดํ„ฐ๋“ค์ž…๋‹ˆ๋‹ค. ํ† ํฐ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ ๊ณ„์ •์ด๋‚˜ ์„ธ์…˜์„ ์˜๋ฏธํ•˜๋Š” ๊ณ ์œ ํ•œ ๋ฐ์ดํ„ฐ๋„ ํฌํ•จ๋  ์ˆ˜ ์žˆ๊ณ  ๊ฐœ์ธ์ •๋ณด๋„ ํฌํ•จ๋ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณด์•ˆ ๋ถ„์„๊ฐ€๋ผ๋ฉด ์ด ๋ถ€๋ถ„์€ ๊ผญ ์ฒดํฌํ•ด์ฃผ์‹œ๊ณ , ๊ฐœ๋ฐœ์ž๋ผ๋ฉด ์ค‘์š”ํ•œ ์ •๋ณด๋Š” ์‚ฌ์šฉ๋˜์ง€ ์•Š๋„๋ก ๊ตฌ์„ฑํ•ด์•ผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Signatrue์— ๋Œ€ํ•œ ๊ฒ€์ฆ๊ณผ ์šฐํšŒ

์ด ๋ฐฉ๋ฒ•์€ ํ† ํฐ ๋‚ด ๊ถŒํ•œ์ด๋‚˜ ์ธ๊ฐ€์— ๊ด€๋ จ๋œ ๊ฐ’์„ ๋ณ€์กฐํ•˜์—ฌ ๊ณต๊ฒฉ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹จ์ˆœํ•˜๊ฒŒ ํ† ํฐ์— ์˜์กดํ•˜์—ฌ ์‚ฌ์šฉ์ž๋ฅผ ์‹๋ณ„ํ•œ๋‹ค๋ฉด ๊ณต๊ฒฉ์ž๋Š” ํ† ํฐ์„ ์œ„์กฐํ•˜์—ฌ ์„œ๋ฒ„๋ฅผ ์†์ผ์ˆ˜๋„ ์žˆ์ฃ . ์„œ๋ฒ„๊ฐ€ ๋ณ„๋‹ค๋ฅธ ๊ฒ€์ฆ์—†์ด ํด๋ผ์ด์–ธํŠธ ์ •๋ณด๋ฅผ ์‹ ๋ขฐํ•œ๋‹ค๋ฉด ์ธ๊ฐ€๋ฐ›์ง€ ์•Š์€ ๋ถ€๋ถ„์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Expire

JWT๋ฅผ ํ† ํฐ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ๋˜ ํ•˜๋‚˜์˜ ๋ฌธ์ œ์ ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๋‹จ์—์„œ๋งŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ธฐ ๋–„๋ฌธ์— ๋ช…์‹œ์  ๋งŒ๋ฃŒ(๋กœ๊ทธ์•„์›ƒ ์‹œ ๊ธฐ์กด ์ฟ ํ‚ค๋ฅผ ํ๊ธฐ)๊ฐ€ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋ฐœ๊ธ‰ ์‹œ ์ ๋‹นํ•œ ์‹œ๊ฐ„์˜ Expire๋ฅผ ๊ฐ€์ ธ์•ผํ•˜๋ฉฐ, ์–ด๋ ค์šด ๊ฒฝ์šฐ ๋ช…์‹œ์  ๋งŒ๋ฃŒ๋ฅผ ๋น„์Šทํ•˜๊ฒŒ ๋‚˜๋งˆ ๊ตฌํ˜„ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

More

์ด ๊ธ€ ์ž‘์„ฑ ๋‹น์‹œ ๋ฌด์ง€ํ–ˆ๋˜ ๋ถ€๋ถ„์ด ์ข€ ๋งŽ์•˜์Šต๋‹ˆ๋‹ค. ๊ณต๊ฒฉ์ž ๊ด€์ , ๋ฐฉ์–ด์ž ๊ด€์ ์—์„œ ํ•„์š”ํ•œ ๋ถ€๋ถ„์€ ์•„๋ž˜์— ๋ณ„๋„๋กœ ์ •๋ฆฌํ•ด๋‘์—ˆ์œผ๋‹ˆ ์ฐธ๊ณ ํ•˜์‹œ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค :D

Licensed under CC BY-NC-SA 4.0
Last updated on Apr 03, 2022 23:23 +0900