Skip to content

Latest commit

ย 

History

History
423 lines (308 loc) ยท 14.3 KB

File metadata and controls

423 lines (308 loc) ยท 14.3 KB

๋ชฉ์ฐจ



1 JWT ๊ฐœ๋…

๐Ÿค” JSON Web Token์ด ๋ฌด์—‡์ธ๊ฐ€?


1-1 JWT๋ž€?

JWT๋ž€?

  • JWT๋Š” ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ (์„œ๋น„์Šค์™€ ์„œ๋น„์Šค ์‚ฌ์ด) ํ†ต์‹ ์‹œ ๊ถŒํ•œ ์ธ๊ฐ€๋ฅผ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ํ† ํฐ์ด๋‹ค.
  • JWT๋Š” ์›นํ‘œ์ค€ RFC 7519์œผ๋กœ์„œ ๋‘ ๊ฐœ์ฒด์—์„œ JSON ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ€๋ณ๊ณ  ์ž๊ฐ€์ˆ˜์šฉ์ ์ธ๋ฐฉ์‹์œผ๋กœ ์ •๋ณด๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์ „๋‹ฌํ•ด์ค€๋‹ค.

์ž๊ฐ€ ์ˆ˜์šฉ์  (self-contained)์ด๋‹ค.

  • JWT๋Š” ํ•„์š”ํ•œ ๋ชจ๋“  ์ •๋ณด๋ฅผ ์ž์ฒด์ ์œผ๋กœ ์ง€๋‹ˆ๊ณ  ์žˆ๋‹ค.
    • ์ค‘๊ฐ„์— ์‰ฝ๊ฒŒ ํƒˆ์ทจํ•˜์—ฌ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฏผ๊ฐํ•œ ์ •๋ณด๋Š” ๋‹ด์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.
    • ์„œ๋ฒ„์—์„œ๋Š” ๋น„๋ฐ€ํ‚ค๋กœ ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ(๋ณ€์กฐ ์œ ๋ฌด)๋งŒ์„ ๊ฒ€์‚ฌํ•œ๋‹ค.

ํ† ํฐ ๊ธฐ๋ฐ˜ ์ธ์ฆ

  • JWT๋Š” ํ† ๊ทผ ๊ธฐ๋ฐ˜ ์ธ์ฆ์˜ ๋ฐฉ๋ฒ•์ค‘ ํ•˜๋‚˜์ด๋‹ค.

1-2 ํ† ํฐ ๊ธฐ๋ฐ˜ ์ธ์ฆ vs ์„œ๋ฒ„ ๊ธฐ๋ฐ˜ ์ธ์ฆ

JWT๋Š” ํ† ํฐ ๊ธฐ๋ฐ˜ ์ธ์ฆ์˜ ๋ฐฉ๋ฒ• ์ค‘ ๋Œ€ํ‘œ์ ์ธ ๋ฐฉ๋ฒ•์ด๋‹ค. ๊ฐ„๋‹จํ•˜๊ฒŒ ํ† ํฐ ๊ธฐ๋ฐ˜๊ณผ ์„œ๋ฒ„ ๊ธฐ๋ฐ˜ ์ธ์ฆ(์„ธ์…˜)์˜ ์ฐจ์ด์ ์„ ์•Œ์•„๋ณด๊ณ ์žํ•œ๋‹ค.


์„œ๋ฒ„ ๊ธฐ๋ฐ˜ ์ธ์ฆ

๐Ÿค” ์„œ๋ฒ„ ๊ธฐ๋ฐ˜ ์ธ์ฆ?


์ถœ์ฒ˜ : https://velopert.com/2350

  • ๊ฐ„๋‹จํžˆ ๋งํ•ด์„œ ์„œ๋ฒ„ ๊ธฐ๋ฐ˜ ์ธ์ฆ์„ "์„ธ์…˜"๊ธฐ๋ฐ˜ ์ธ์ฆ์„ ์˜๋ฏธํ•œ๋‹ค.
    • ์„œ๋ฒ„์ธก์—์„œ ์‚ฌ์šฉ์ž๋“ค์˜ ์ •๋ณด๋ฅผ ๊ธฐ์–ตํ•˜๊ณ  ์žˆ์–ด์•ผ ํ•œ๋‹ค.
    • ์‚ฌ์šฉ์ž๋“ค์˜ ์ •๋ณด๋ฅผ ๊ธฐ์–ตํ•˜๊ธฐ ์œ„ํ•ด์„œ ์„ธ์…˜์„ ์ด์šฉํ•œ๋‹ค.
  • ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์„ stateful ํ•˜๋‹ค๊ณ  ํ•œ๋‹ค.
    • ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„์˜ ๋™์ž‘, ์ƒํƒœ ์ •๋ณด๋“ฑ์„ ์ €์žฅํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์„ธ์…˜ ์ƒํƒœ์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ ์„œ๋ฒ„์˜ ์‘๋‹ต์ด ๋‹ฌ๋ฆฌ์ง„๋‹ค.
  • ๋‹จ์ 
    • ์„ธ์…˜
      • ์„ธ์…˜์€ ๋ณดํ†ต ๋ฉ”๋ชจ๋ฆฌ์— ์ด๋ฅผ ์ €์žฅํ•˜๋Š”๋ฐ, ์ด์šฉ์ž ์ˆ˜๊ฐ€ ๋งŽ์•„์ง€๋ฉด ๋žจ ๋Œ€์‹  DB๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋Š”๋ฐ ์„œ๋ฒ„ ์„ฑ๋Šฅ์— ๋ฌด๋ฆฌ๋ฅผ ์ค„ ์ˆ˜ ์žˆ๋‹ค.
    • ๋ถ„์‚ฐ ์„œ๋ฒ„ ์‹œ์Šคํ…œ ๋น„ํšจ์œจ์ 
      • ํŠธ๋ž˜ํ”ฝ์ด ์ฆ๊ฐ€ํ•จ์— ๋”ฐ๋ผ ๋ถ„์‚ฐ ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค๊ฒŒ ๋˜๋ฉด ์„ธ์…˜์œผ๋กœ๋Š” ๋ถ„์‚ฐ ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค๊ธฐ ๋งค์šฐ ๋ณต์žกํ•˜๋‹ค.
    • CORS (Cross - Origin Resource Sharing)
      • ์„ธ์…˜์„ ๊ด€๋ฆฌํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ์ฟ ํ‚ค๋Š” ๋‹จ์ผ ๋„๋ฉ”์ธ ๋ฐ ์„œ๋ธŒ ๋„๋ฉ”์ธ์—์„œ๋งŒ ์ž‘๋™ํ•˜๋„๋ก ์„ค๊ณ„๋˜์–ด์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ฟ ํ‚ค๋ฅผ ์—ฌ๋Ÿฌ ๋„๋ฉ”์ธ์—์„œ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์€ ๋ฒˆ๊ฑฐ๋กญ๋‹ค.

์ข‹์€ ๋ธ”๋กœ๊ทธ ๋‚ด์šฉ: https://sanghaklee.tistory.com/47


ํ† ํฐ ๊ธฐ๋ฐ˜ ์ธ์ฆ

๐Ÿค” ํ† ํฐ ๊ธฐ๋ฐ˜ ์ธ์ฆ?


์ถœ์ฒ˜ : https://velopert.com/2350

  • ์ธ์ฆ๋ฐ›์€ ์‚ฌ์šฉ์ž๋“ค์—๊ฒŒ ํ† ํฐ์„ ๋ฐœ๊ธ‰ํ•˜๊ณ , ์„œ๋ฒ„์— ์š”์ฒญ์„ ํ•  ๋•Œ ํ—ค๋”์— ํ† ํฐ์„ ํ•จ๊ป˜ ๋ณด๋‚ด๋„๋ก ํ•˜์—ฌ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ํ•œ๋‹ค.
    • ์œ ์ €๊ฐ€ ์•„์ด๋””์™€ ๋น„๋ฐ€๋ฒˆํ˜ธ๋กœ ๋กœ๊ทธ์ธ ํ•œ๋‹ค.
    • ์„œ๋ฒ„์ธก์—์„œ ํ•ด๋‹น ๊ณ„์ •์ •๋ณด๋ฅผ ๊ฒ€์ฆํ•œ๋‹ค.
    • ๊ณ„์ • ์ •๋ณด๊ฐ€ ์ •ํ™•ํ•˜๋‹ค๋ฉด, ์„œ๋ฒ„์ธก์—์„œ ์œ ์ €์—๊ฒŒ signedํ† ํฐ์„ ๋ฐœ๊ธ‰ํ•ด์ค€๋‹ค.
      • ์—ฌ๊ธฐ์„œ signed์˜ ์˜๋ฏธ๋Š” ํ•ด๋‹น ํ† ํฐ์ด ์„œ๋ฒ„์—์„œ ์ •์ƒ์ ์œผ๋กœ ๋ฐœ๊ธ‰๋œ ํ† ํฐ์ž„์„ ์ฆ๋ช…ํ•˜๋Š” signature๋ฅผ ์ง€๋‹ˆ๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ.
    • ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ์ „๋‹ฌ๋ฐ›์€ ํ† ํฐ์„ ์ €์žฅํ•ด๋‘๊ณ , ์„œ๋ฒ„์— ์š”์ฒญ์„ ํ•  ๋•Œ๋งˆ๋‹ค, ํ•ด๋‹น ํ† ํฐ์„ ํ•จ๊ป˜ ์„œ๋ฒ„์— ์ „๋‹ฌํ•œ๋‹ค.
    • ์„œ๋ฒ„๋Š” ํ† ํฐ์„ ๊ฒ€์ฆํ•˜๊ณ , ์š”์ฒญ์— ์‘๋‹ตํ•œ๋‹ค.

์ค‘์š”ํ•œ ์ ์€ ํ† ํฐ์˜ ์ •๋ณด๋Š” ์‰ฝ๊ฒŒ ํƒˆ์ทจํ•˜์—ฌ ๋ณผ ์ˆ˜ ์žˆ์ง€๋งŒ, ๋ณ€์กฐ๋ฅผ ํ•˜๊ฒŒ ๋˜๋ฉด ์ธ์ฆ์ด ์•ˆ๋œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. (๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ)


ํ† ํฐ์˜ ์žฅ์ 

  • ๋ฌด์ƒํƒœ (stateless)์ด๋ฉฐ ํ™•์žฅ์„ฑ (scalability)์ด ์žˆ๋‹ค.
    • ํ† ํฐ์„ ํด๋ผ์ด์–ธํŠธ์‚ฌ์ด๋“œ์— ์ €์žฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— stateless
    • ์„œ๋ฒ„๋ฅผ ํ™•์žฅํ•˜์—ฌ ์–ด๋–ค ์„œ๋ฒ„์— ์š”์ฒญ์„ ํ•ด๋„ ๊ฐ™์€ ์ƒ๊ด€์—†๋‹ค. scalability
  • ๋ณด์•ˆ์„ฑ
    • ์ฟ ํ‚ค์˜ ๋ณด์•ˆ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐ๊ฐ€๋Šฅํ•˜๋‹ค. ํ•˜์ง€๋งŒ ํ† ํฐ์˜ ๋ณด์•ˆ์„ฑ๋„ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค.
  • Extensibility (ํ™•์žฅ์„ฑ)
    • ํ† ํฐ์„ ์ด์šฉํ•ด ๋‹ค๋ฅธ ์„œ๋น„์Šค์—์„œ๋„ ๊ถŒํ•œ์„ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋‹ค. (facebook, github...)
  • ์—ฌ๋Ÿฌ ํ”Œ๋žซํผ ๋ฐ ๋„๋ฉ”์ธ
    • ํ† ํฐ์€ CORS๋ฅผ ๋งŒ์กฑํ•œ๋‹ค. ํ—ค๋”์˜ ๊ฐ’์„ ํ†ตํ•ด์„œ ํ† ํฐ์„ ์ „๋‹ฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ๋Ÿฌ ๋””๋ฐ”์ด์Šค๋ฅผ ํ˜ธํ™˜ํ•œ๋‹ค.

1-3 JWT ๊ตฌ์กฐ์™€ ์ƒ์„ฑ

HEADER.PAYLOAD.SIGNATURE

JWT๋Š” ์ ์„ ๊ธฐ์ค€์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌ์„ฑ๋œ๋‹ค.

  • ํ—ค๋” (Header)
  • ํŽ˜์ด๋กœ๋“œ (Payload)
  • ์„œ๋ช… (Signature)

JWT๋ฅผ ๊ฒ€์ฆํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ๊ฐ€์ง„ JSON๊ฐ์ฒด๋Š” Base64 URL-Safe ์ธ์ฝ”๋”ฉ๋œ ๋ฌธ์ž์—ด์ด๋‹ค.


Header

ํ—ค๋”๋Š” JWT๋ฅผ ์–ด๋–ป๊ฒŒ ๊ฒ€์ฆ(Verify)ํ•˜๋Š”๊ฐ€์— ๋Œ€ํ•œ ๋‚ด์šฉ์„ ๋‹ด๊ณ  ์žˆ๋‹ค.

{
  "alg" : "HS256",
  "typ" : "JWT"
}
  • alg - ์„œ๋ช… ์‹œ ์‚ฌ์šฉํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜.
    • ์ด ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ํ† ํฐ์„ ๊ฒ€์ฆํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋Š” signature ๋ถ€๋ถ„์—์„œ ์‚ฌ์šฉ๋œ๋‹ค.
  • typ - ํ† ํฐ์˜ ํƒ€์ž…์„ ์ง€์ •.

Base64๋กœ ์•”ํ˜ธํ™”๋˜์–ด์žˆ์–ด, ๋ˆ„๊ตฌ๋‚˜ ํƒˆ์ทจํ•˜๋ฉด ๋ณตํ˜ธํ™”ํ•˜์—ฌ ์ •๋ณด๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์ฆ‰, ์ค‘์š” ๋‚ด์šฉ์€ ๋„ฃ์œผ๋ฉด ์•ˆ๋œ๋‹ค.


Payload

Payload๋Š” JWT์˜ ๋‚ด์šฉ์„ ๋‹ด๊ณ  ์žˆ๋‹ค.

Payload์— ๋‹ด๋Š” ์ •๋ณด์˜ ํ•œ ๋‹จ์œ„๋ฅผ ํด๋ ˆ์ž„ (Claim)์ด๋ผ ํ•˜๋ฉฐ, name / value ํ˜•ํƒœ๋กœ ๋˜์–ด ์žˆ๋‹ค.

Payload์— ์žˆ๋Š” ์†์„ฑ๋“ค์„ **ํด๋ ˆ์ž„ ์…‹ (Claim Set)**์ด๋ผ ๋ถ€๋ฅธ๋‹ค.

{
  "uid" : "19234",
  "userName" : "binghe"
}
  • Claim์˜ ์ข…๋ฅ˜
    • ๋“ฑ๋ก๋œ (registered) ํด๋ ˆ์ž„ - ์ด๋ฏธ ์˜ˆ์•ฝ๋œ Claim
      • <iss>: ํ† ํฐ ๋ฐœํ–‰์ž (Issur)
      • <sub>: ํ† ๋ฅธ ์ œ๋ชฉ (Subject)
      • <aud>: ํ† ํฐ ๋Œ€์ƒ์ž (Audience)
      • <exp>: ํ† ํฐ ๋งŒ๋ฃŒ์‹œ๊ฐ„. (Expiration Time)
      • <nbf>: ํ† ํฐ์ด ํ™œ์„ฑ๋˜๋Š” ์‹œ๊ฐ„. (์ด ์‹œ๊ฐ„ ์ดํ›„์— ํ† ํฐ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค)
      • <jti>: JWT์˜ ๊ณ ์œ  ์‹๋ณ„์ž. (๋‹ค๋ฅธ JWT์™€ ๋‹ค๋ฅธ Uniqueํ•œ ๊ฐ’์„ ์ง€๋…€์•ผ ํ•œ๋‹ค)
    • ๊ณต๊ฐœ (public) ํด๋ ˆ์ž„ - ์‚ฌ์šฉ์ž ์ •์˜ Claim
      • JWT๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์— ์˜ํ•ด ์ •์˜๋˜๋Š” Claim
      • ์ถฉ๋Œ ๋ฐฉ์ง€๋ฅผ ์œ„ํ•ด URI ํฌ๋งท์„ ์ด์šฉํ•ด ์ €์žฅํ•œ๋‹ค.
    • ๋น„๊ณต๊ฐœ (private) ํด๋ ˆ์ž„ - ์‚ฌ์šฉ์ž ์ •์˜ Claim
      • JWT ์‚ฌ์šฉ์ž์™€ ์ƒ์‚ฐ์ž ์ƒํ˜ธ ํ•ฉ์˜ ํ•˜์— ์ •ํ•ด์ง€๋Š” Claim
      • ์ผ๋ฐ˜์ ์ธ ์ •๋ณด๋ฅผ ์ €์žฅํ•œ๋‹ค. (์ด๋ฆ„์˜ ์ถฉ๋Œ ์œ„ํ—˜์ด ์žˆ๋‹ค.)

Base64๋กœ ์•”ํ˜ธํ™”๋˜์–ด์žˆ์–ด, ๋ˆ„๊ตฌ๋‚˜ ํƒˆ์ทจํ•˜๋ฉด ๋ณตํ˜ธํ™”ํ•˜์—ฌ ์ •๋ณด๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์ฆ‰, ์ค‘์š” ๋‚ด์šฉ์€ ๋„ฃ์œผ๋ฉด ์•ˆ๋œ๋‹ค.


Signature

์ ์„ ๊ตฌ๋ถ„์ž๋กœ ํ•ด์„œ Header์™€ Payload๋ฅผ ํ•ฉ์นœ ๋ฌธ์ž์—ด์„ ์„œ๋ช…ํ•œ ๊ฐ’์ด๋‹ค.

// ์ƒ์„ฑ ๋ฐฉ์‹
HSACSHA256 (
	base64UrlEncode(header) + "." +
	base64UrlEncode(payload),
	secret
)
  • Signature์€ ๋ฐ์ดํ„ฐ์˜ ๋ฌด๊ฒฐ์„ฑ(๋ณ€์กฐ์œ ๋ฌด)๋ฅผ ์ž…์ฆํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.
    • ๋ฐ์ดํ„ฐ๊ฐ€ ์ค‘๊ฐ„์— ํƒˆ์ทจ๋˜์–ด, Header๋‚˜ Payload๊ฐ€ ๋ณ€์กฐ๋˜์—ˆ๋‹ค๋ฉด Signature ๊ฒ€์ฆ์„ ํ†ตํ•ด ์•Œ์•„๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

1-4 ์•”ํ˜ธํ™” ๋ฐฉ์‹

JWT์˜ Signature ๋ถ€๋ถ„์€ message(header + payload)๊ฐ€ ๋ณ€์กฐ๋˜์—ˆ๋Š”์ง€ ๊ฒ€์‚ฌํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ด๋ฅผ ์•”ํ˜ธํ™”ํ•˜๊ณ  ๊ฒ€์ฆํ•˜๋Š” ๋ฐฉ์‹์€ ๋‘ ๊ฐ€์ง€์ด๋‹ค.


๋น„๋Œ€์นญํ‚ค - RS256

RS256: RSA Signature with SHA-256

๋น„๋Œ€์นญํ‚ค์— ๋Œ€ํ•œ ๊ฐœ๋…์€ ์—ฌ๊ธฐ์—์„œ ํ™•์ธ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค :)

  • ๋น„๋Œ€์นญํ‚ค ๋ฐฉ์‹
    • message์— SHA256 ์ ์šฉํ›„, private key ์‚ฌ์šฉํ•ด์„œ ์•”ํ˜ธํ™”ํ•œ๋‹ค.
    • ์ผ๋ฐ˜์ ์œผ๋กœ public key๋Š” JWT๋ฅผ ๋ฐœ๊ธ‰ํ•œ ์„œ๋ฒ„์—์„œ JWK (Json Web Key)์— ์ •์˜๋œ ๋ฐฉ์‹์„ ํ†ตํ•ด ๊ณต๊ฐœ์ ์œผ๋กœ ์ œ๊ณต๋œ๋‹ค.

๋Œ€์นญํ‚ค - HS256

HS256: HMAC with SHA-256

๋Œ€์นญํ‚ค์— ๋Œ€ํ•œ ๊ฐœ๋…์€ ์—ฌ๊ธฐ์—์„œ ํ™•์ธ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค :)

  • ๋กœ๊ทธ์ธ ์š”์ฒญ์„ ๋ฐ›๊ณ  ์ธ์ฆ์ด ๋˜์—ˆ๋‹ค๋ฉด Header(Base64url)์™€ Payload(Base64Url) ๋‚ด์šฉ์œผ๋กœ secret key์™€ ํ•จ๊ป˜ Signature๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
    • ์ฆ‰, Header์™€ Payload์— SHA256 ์ ์šฉ ํ›„ ๋Œ€์นญํ‚ค(secret key) ์‚ฌ์šฉํ•ด์„œ ์•”ํ˜ธํ™”
    • ํ•ด๋‹น ๋Œ€์นญํ‚ค๋ฅผ ๊ฐ€์ง„ ์ฃผ์ฒด๋“ค์€ ๋ชจ๋‘ Signature ์œ ํšจ์„ฑ ๊ฒ€์ฆ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

๋” ์ •ํ™•ํ•œ ์›๋ฆฌ๋Š” JWT ๊ณต์‹ ํ™ˆํŽ˜์ด์ง€์—์„œ ํ™•์ธ๊ฐ€๋Šฅํ•˜๋‹ค.


2 JJWT

JWT (JSON Web Token) : JWS or JWE

JWS (JSON Web Signature) : ์„œ๋ฒ„์—์„œ ์ธ์ฆ์„ ํ•˜๊ณ  ์ธ์ฆ ์ •๋ณด์™€ private key (secret key)๋กœ ์„œ๋ช…ํ•œ Token. (String => header.payload.signature)

JWE (JSON Web Encryption) : ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ๊ฐ„ ์•”ํ˜ธํ™”๋œ ๋ฐ์ดํ„ฐ๋ฅผ Token ํ™” ํ•œ๊ฒƒ.

JWK (JSON Web Key) : JWE ์—์„œ payload encryption ์— ์“ฐ์ธ ํ‚ค๋ฅผ token ํ™” ํ•œ๊ฒƒ. (๋ฌผ๋ก , ํ‚ค ์ž์ฒด๋„ ์•”ํ˜ธํ™”๋˜์–ด ์žˆ์ฃ .)


2-1 JWS ์ƒ์„ฑ

JWS๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

String jws = Jwts.builder()
    .setSubject("binghe")
    .signWith(key)
    .compact();
  1. Jwts.builder() ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•ด JwtBuilder์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
  2. JwtBuilder ๋ฉ”์„œ๋“œ ์ฒด์ด๋‹์„ ํ†ตํ•ด ํ—ค๋”์™€ ํŽ˜์ด๋กœ๋“œ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.
  3. JWT๋ฅผ ๊ฒ€์ฆํ•  ๋•Œ ์‚ฌ์šฉํ•  SecretKey ํ˜น์€ ๋น„๋Œ€์นญ์„ฑ์˜ PrivateKey๋ฅผ ์„ค์ •ํ•ด์ค€๋‹ค.
  4. compact() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฏ€๋กœ์จ jws๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

์‰ฝ๊ฒŒ ์–˜๊ธฐํ•˜๋ฉด ๋นŒ๋” ํŒจํ„ด์œผ๋กœ ๋ฉ”์„œ๋“œ ์ฒด์ด๋‹์„ ํ†ตํ•ด ๊ฐ๊ฐ์˜ ์„ค์ •์„ ํ•ด์ฃผ๊ณ  ๋งŒ๋“ ๋‹ค๋Š” ๊ฒƒ.


Header

header parameter

String jws = Jwts.builder()
    .setHeaderParam("kid", "binghe")
    // ....
  • ์„ค์ •ํ•ด์ฃผ๊ณ  ์‹ถ์€ ํ—ค๋”๋ฅผ setHeaderParam์„ ํ†ตํ•ด ์„ค์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค. (key - value)
    • ์—ฌ๋Ÿฌ๋ฒˆ ํ˜ธ์ถœํ•ด๋„ ๋‚ด๋ถ€์˜ Header ์ธ์Šคํ„ด์Šค์— append๋œ๋‹ค.
    • ๋งŒ์•ฝ ๋™์ผํ•œ key๋ฅผ ์„ธํŒ…ํ•ด์ฃผ๋ฉด ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰ ๊ฒƒ์œผ๋กœ ์˜ค๋ฒ„๋ผ์ด๋”ฉ๋œ๋‹ค.
  • alg๋‚˜ zipํ—ค๋”๋ฅผ ์„ค์ •ํ•ด์ฃผ์ง€ ์•Š์•„๋„ ์ž๋™์ ์œผ๋กœ ์„ค์ •ํ•ด์ค€๋‹ค.

Header ์ธ์Šคํ„ด์Šค

Header header = Jwts.header(); // Map<String, Object>์˜ ๊ตฌํ˜„์ฒด
header.put(key, value);
...

String jws = Jwts.builder()
    .setHeader(header)
    // ...
  • setHeader๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์ด๋ฏธ ์„ค์ •๋˜์–ด์žˆ์„ ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๋™์ผํ•œ ํ—ค๋” key-value ์Œ์„ ๋ฎ์–ด์“ด๋‹ค.
  • ๊ทธ๋Ÿฌ๋‚˜ ๋ชจ๋“  ๊ฒฝ์šฐ์— JJWT๋Š” ์ง€์ •๋œ ํ—ค๋” ๊ฐ์ฒด์— ์žˆ๋“  ์—†๋“  ์ƒ๊ด€์—†์ด ๋ชจ๋“  alg์™€ zipํ—ค๋”๋ฅผ ์„ค์ •ํ•ด์ค€๋‹ค.

Header Map

Map<String, Object> header = new Map<String, Object>();
header.set(key, value);
...

String jws = Jwts.builder()
    .setHeader(header)
    // ...
  • Header ์ธ์Šคํ„ด์Šค์™€ ๋™์ผํ•˜๋‹ค.

Claims

Claims๋Š” JWT์˜ ๋ณธ๋ฌธ์ด๋ฉฐ, JWT ์ž‘์„ฑ์ž๊ฐ€ JWT ์ˆ˜๋ น์ธ์—๊ฒŒ ์ œ์‹œํ•˜๊ณ ์ž ํ•˜๋Š” ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ๋‹ค.


Standard Claims

String jws = Jwts.builder()

    .setIssuer("me")
    .setSubject("Bob")
    .setAudience("you")
    .setExpiration(expiration) //a java.util.Date
    .setNotBefore(notBefore) //a java.util.Date 
    .setIssuedAt(new Date()) // for example, now
    .setId(UUID.randomUUID()) //just an example id
    
    /// ... etc ...

Custom Claims ํ‘œ์ค€ Claims๋ง๊ณ  ์‚ฌ์šฉ์ž ์ง€์ • ํด๋ ˆ์ž„์„ ์„ค์ •ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•˜๋ฉด ๋œ๋‹ค.

String jws = Jwts.builder()
    .claim("hello", "World")
    .claim("name", "binghe")
    // ....
  • claim์ด ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค key-value ์Œ์„ ๋‚ด๋ถ€ Claim ์ธ์Šคํ„ด์Šค์— ์ถ”๊ฐ€ํ•œ๋‹ค.
    • ๋งŒ์•ฝ ๋™์ผํ•œ ๊ธฐ์กด key-value๊ฐ€ ์žˆ๋‹ค๋ฉด ๋ฎ์–ด์“ด๋‹ค.
  • ํ‘œ์ค€ claim์€ ๊ฐ€๋…์„ฑ ํ–ฅ์ƒ์„ ์œ„ํ•ด ํ‘œ์ค€ setter ๋ฐฉ์‹์ด ๋” ์ข‹๋‹ค๊ณ  ํ•œ๋‹ค.

Claim ์ธ์Šคํ„ด์Šค ๋ชจ๋“  Claim์„ ํ•œ ๋ฒˆ์— ์ง€์ •ํ•˜๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค์ •ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

Claims claims = Jwts.claims(); // Map<String, Object>์˜ ๊ตฌํ˜„์ฒด
claims.put(key, value);

String jws = Jwts.builder()
    .setClaims(claims)
    // ...
  • setClaims๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์ด๋ฏธ ์„ค์ •๋˜์–ด์žˆ์„ ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๋™์ผํ•œ Claim key-value ์Œ์„ ๋ฎ์–ด์“ด๋‹ค.

Claims Map

Map<String, Object> claims = new Map<String, Object>();
claims.set(key, value);
...

String jws = Jwts.builder()
    .setClaims(header)
    // ...
  • Claims ์ธ์Šคํ„ด์Šค์™€ ๋™์ผํ•˜๋‹ค.

2-2 JWS ์ฝ๊ธฐ

JWS์˜ ์ฝ๊ธฐ(ํŒŒ์‹ฑ)์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆœ์„œ๋กœ ์ด๋ค„์ง„๋‹ค.

  1. Jwts.parserBuilder()์„ ์‚ฌ์šฉํ•˜์—ฌ JwtParserBuilder` ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ ๋‹ค.
  2. JWS ์„œ๋ช…์„ ํ™•์ธํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  secret key ๋˜๋Š” ๋น„๋Œ€์นญ public key๋ฅผ ์ง€์ •ํ•œ๋‹ค.
  3. ์Šค๋ ˆ๋“œ ์•ˆ์ „ํ•œ JwtParser๋ฅผ ๋ฐ˜ํ™˜๋ฐ›์œผ๋ ค๋ฉด JwtParserBuilder์˜ build()๋ฅผ ํ˜ธ์ถœํ•ด์•ผํ•œ๋‹ค.
  4. ๋งˆ์ง€๋ง‰์œผ๋กœ jws (String)์„ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ parseClaimsJws(String)์„ ํ˜ธ์ถœํ•˜๋ฉด ์›๋ž˜์˜ JWS๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
  5. ์ „์ฒด ์ฝ”๋“œ๋Š” ๊ตฌ๋ฌธ ๋ถ„์„ ๋˜๋Š” ์„œ๋ช… ๊ฒ€์ฆ์ด ์‹คํŒจํ•  ๊ฒฝ์šฐ๋ฅผ ์œ„ํ•ด try/catch๋กœ ๊ฐ์‹ธ์•ผํ•œ๋‹ค.
Jws<Claims> jws;

try {
    jws = Jwts.parserBuilder()  // (1)
    .setSigningKey(key)         // (2)
    .build()                    // (3)
    .parseClaimsJws(jwsString); // (4)
    
    // we can safely trust the JWT
     
catch (JwtException ex) {       // (5)
    
    // we *cannot* use the JWT as intended by its creator
}

๋” ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์—ฌ๊ธฐ๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”!


์ฐธ๊ณ