你必須很努力

Day09 - Gem-jwt 介紹與應用

2021/09/22
字數統計: 629閱讀時間: 2 min

前言

JWT 是 JSON Web Token 的縮寫。在寫此篇時,發現已經有許多相關文章可參考,故本篇以實作為主,若想知道更深入部分,可直接看參考資料

JWT組成

HeaderPayloadSignature 所組成的字串,中間以 . 做間隔

1
2
3
4
5
# 寫成一行的話,組成如下
Header.Payload.Signature

# 實際範例如下 (中間以 . 做間隔)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

組成 說明
Header 通常由演算法簽章、 Token 類型所組成的 JSON,再做 Base64 URL 編碼
Payload 需傳遞的資料放這
Signature Header、Payload、密鑰 (secret) 透過雜湊演算法所產生

最終資料呈現如下方圖左,是一個字串

動手做看看

官方 JWT 首頁已有範例,這邊以 Ruby 做演練

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 在 irb 中操作

require "json"
require "base64"
require "openssl"

header = { "alg" => "HS256", "typ" => "JWT" }
header_json = header.to_json # or JSON(header)
encoded_header = Base64.urlsafe_encode64(header_json, padding: false) # Base64 編碼 header


payload = { "sub" => "1234567890", "name" => "John Doe", "iat" => 1516239022 }
payload_json = payload.to_json # or JSON(payload)
encoded_payload = Base64.urlsafe_encode64(payload_json, padding: false) # Base64 編碼 payload


secret_key = "your-256-bit-secret"
data = "#{encoded_header}.#{encoded_payload}"
digest = OpenSSL::Digest::SHA256.new # 使用 SHA256 演算法
signature = OpenSSL::HMAC.digest(digest, secret_key, data) # 透過 HMAC 演算法簽章
encoded_signature = Base64.urlsafe_encode64(signature, padding: false) # Base64 編碼 signature


token = "#{encoded_header}.#{encoded_payload}.#{encoded_signature}"

# 驗證,與 JWT 首頁範例一樣
token == "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"

使用 RubyGems

上述為手動實作,透過實作能更清楚如何運作 也可直接使用 jwt gem 來處理,一切變得簡單多了,有興趣可看下 source code 部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 使用 ruby-jwt gem 實作

hmac_secret = "your-256-bit-secret"
payload = { "sub" => "1234567890", "name" => "John Doe", "iat" => 1516239022 }

token = JWT.encode payload, hmac_secret, "HS256"

decoded_token = JWT.decode token, hmac_secret, true, { algorithm: "HS256" }
# # Array (payload + header)
# [
# {
# "sub" => "1234567890",
# "name" => "John Doe",
# "iat" => 1516239022
# },
# {
# "alg" => "HS256"
# }
# ]

小結

JWT 的特色有「JSON 通用性的關係,可跨語言使用」、「構造簡單,size 小,便於傳輸」...等

在使用 JWT 時,不建議把敏感資料放裡面,只要解碼 Base64 便能看到原本的資料

推薦下面參考資料可以都看過一輪

參考資料

  1. https://jwt.io/
  2. JSON Web Token Wiki
  3. ruuby-jwt
  4. 是誰在敲打我窗?什麼是 JWT ?
  5. 見令如見人,介紹 JWT
  6. [筆記] 透過 JWT 實作驗證機制
  7. JSON Web Token 入门教程
  8. JSON Web Token(JWT) 簡單介紹

鐵人賽文章連結:https://ithelp.ithome.com.tw/articles/10264580
medium 文章連結:https://link.medium.com/OYkJftn2Mjb
本文同步發布於 小菜的 Blog https://riverye.com/

備註:之後文章修改更新,以個人部落格為主

原文連結:https://riverye.com/2021/09/22/Day09-Gem-jwt-介紹與應用/

發表日期:2021-09-22

更新日期:2022-12-21

CATALOG
  1. 1. 前言
  2. 2. JWT組成
  3. 3. 最終資料呈現如下方圖左,是一個字串
  4. 4. 動手做看看
  5. 5. 使用 RubyGems
  6. 6. 小結
  7. 7. 參考資料