見令如見人,介紹 JWT
最近工作上需要用 JWT來互傳資訊,
覺得這東西用起來是滿簡單的.
只是結合多個概念,一開始不是很好懂,紀錄下理解的過程.
最後再介紹利用
jwt
這個 보석.來制作 jwtTL;박사 01 명
個人觀點,不要打我 이자의를 제거한다
參考資料
왜?
先不提 JWT怎麼實做的,先想像班上有一對情侶 다스틴跟 수시...
兩人都是 바보
所以在教室最後一排的 다스틴要傳紙條給第一排的 서양的時候,
竟然是用 JSON的格式!
{
"from": "Dustin",
"to": "Suzie",
"message": "Do you want to have dinner with me tonight?",
"place": "MacDonald's"
}
不過傳紙條的過程中,
班上就是會有人硬要打開不是給他的紙條,
比如 웨일就是打開紙條並把內容改成
{
"from": "Dustin",
"to": "Erica", // 被 Will 改了
"message": "Do you want to have dinner with me tonight?",
"place": "MacDonald's"
}
於是不僅當晚 다스틴只能孤零零一個人吃大麥克,
서양還不理他一個禮拜,悲劇.
其實一切就是他沒辦法控制發出去的訊息會不會被篡改.
後來 다스틴記取教訓,
事先跟 서양約定好一個暗號 NeverEndingStory
並將訊息用 HMAC SHA-256
搭配 NeverEndingStory
這個暗號製作一串亂碼,
先直接接受HMAC SHA-256
搭配相同的暗號跟訊息,會產出唯一的亂碼
再把亂碼寫在紙條的最下面
796e0c718cc2768edfb67a53b0f4fed74b4abbac61baaa68876630d9827714a0
서양打開紙條後即可以用暗號 NeverEndingStory
以相同的方式將紙上的訊息轉成亂碼,
再檢查和紙上附的亂碼是否一致, 就知道訊息是完整且沒被修改過.
這樣就可以避免再次發生悲劇了.
可以任意找一個線上的 HMAC SHA256轉換器來驗證 Free HMAC-SHA256 Online Generator Tool | Devglan
只要訊息跟算出來的亂碼不合,即知道訊息已遭到修改或者不完全.
所以這樣產生出來的亂碼很常被叫做數位簽名
JWT就是給 JSON加上一個簽名,確保訊息沒有被任何人動過.
變得好像可以宣告一個 콘스트的 JSON再傳送出去一樣,
JWT的組成
JWT最後的呈現是一串字串,有셋個部分,以 .
分開
{
"from": "Dustin",
"to": "Suzie",
"message": "Do you want to have dinner with me tonight?",
"place": "MacDonald's"
}
{
"from": "Dustin",
"to": "Erica", // 被 Will 改了
"message": "Do you want to have dinner with me tonight?",
"place": "MacDonald's"
}
先直接接受HMAC SHA-256
搭配相同的暗號跟訊息,會產出唯一的亂碼
796e0c718cc2768edfb67a53b0f4fed74b4abbac61baaa68876630d9827714a0
JWT最後的呈現是一串字串,有셋個部分,以
.
分開左邊即為製作出來的 JWT
我想這時已經有人握緊拳頭了...
聽你鬼扯!
這個 JWT 看起來根本就只是一串亂碼!
什麼 JSON 、指定的演算法跑到哪裡去了?
上面的確是漏說了一些細節 😂
헤드, 페이로드其實是會先經由 base64去編碼
base64就是個編碼的方式,可理解成一個可編碼及還原的方法.
可參考上篇文章
그물 모양의 물건傳輸的摩斯密碼,base64介紹
로케빈・ 2월 22일・ 2분 읽기
#ruby
#base64
#chinese
#binarydata
所以紅色部色就是헤딩紫色部分就是 JSON
這邊用 루비來試著驗證看看
header = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9'
payload = 'eyJuYW1lIjoiS2V2aW4ifQ'
# 用 base64 去解碼,可得到原始內容
require 'base64'
puts Base64.urlsafe_decode64(header)
# {"alg":"HS256","typ":"JWT"}
puts Base64.urlsafe_decode64(payload)
# {"name":"Kevin"}
# 用 JWT 的方式,把 header 跟 payload 連起來
# 用 HMAC SHA256 的方式產生簽名
require 'openssl'
mac = OpenSSL::HMAC.hexdigest("SHA256", 'mySecret', "#{header}.#{payload}")
Base64.urlsafe_encode64(mac).gsub('=', '') # '=' is just padding
# "IMa4S4W1LMP1xuKVglwBagrHA5wwK9sBu-CVDKudIkg"
# 跟網站上產出的一樣喔,表示訊息沒被動過
可能會疑惑怎麼可以直接把 페이로드還原成 JSON那 JWT裡的資料不就大辣辣地秀出,這樣不是不安全?
沒錯...因為 JWT好像變成一串亂碼,容易誤會它很安全,
其實它跟加密完全沒有關係 이자의를 제거한다
(加密完全是 TLS也就是 https的事,先忽略吧)
JWT 主要在乎資料是否被篡改, Signature 是否一致而已
所以別把敏感的資訊放在裡面.
我們可以先看實際使用 JWT的程式碼
데모
因為我主要用 루비,這邊利用 jwt
這個 보석.來데모
不過幾乎所有的語言都有實作 jwt
可在 JSON Web Tokens - jwt.io 查找相關資源.
require 'jwt'
payload = {
first_name: 'Kevin',
last_name: 'Luo'
}
secret = "my secret"
token = JWT.encode payload, secret, 'HS256'
# "eyJhbGciOiJIUzI1NiJ9.eyJmaXJzdF9uYW1lIjoiS2V2aW4iLCJsYXN0X25hbWUiOiJMdW8ifQ.dZJnejsQ9cWs1hyOvCAij_Q4k87vfbQpeBIjgqYCrgs"
decoded_token = JWT.decode token, secret, true, { algorithm: 'HS256' }
# [{"first_name"=>"Kevin", "last_name"=>"Luo"}, {"alg"=>"HS256"}]
此外,JWT的格式RFC其實有約定一些參數可以設定,
不過端看程式有沒有做對應的處理.
一個常用的是「到期時間」 exp
,設定一個到期時間給 JWT,假使真的到期,디코딩時即丟出 JWT::ExpiredSignature
這個 예외
require 'jwt'
exp = Time.now.to_i + 3600 # 1 hour
exp_payload = { data: payload, exp: exp }
token = JWT.encode exp_payload, secret, 'HS256'
# "eyJhbGciOiJIUzI1NiJ9.eyJkYXRhIjp7ImZpcnN0X25hbWUiOiJLZXZpbiIsImxhc3RfbmFtZSI6Ikx1byJ9LCJleHAiOjE2MTM4ODU4MjF9.1_NIKXDnBVz1G6Li7_CZbcDwIk5AFaOsreK7BFDS13Q"
begin
decoded_token = JWT.decode token, secret, true, { algorithm: ‘HS256’ }
# [{"data"=>{"first_name"=>"Kevin", "last_name"=>"Luo"}, "exp"=>1613885821}, {"alg"=>"HS256"}]
rescue JWT::ExpiredSignature
# 過期
end
應用
JWT除了可以讓 2台有共同 비밀.的電腦可互傳確認不會被篡改的資料外,
最常見的情境應該就是後端 미국 석유 학회使用者登入後發給前端的 토큰了吧.
會用 미국 석유 학회的 청원的 타이틀中所帶的 토큰 머니來判斷來源是否可以取用該 미국 석유 학회
雖然拿 JWT當 토큰 머니因為前端應該是不會有共有的 비밀.
沒辦法去驗證訊息,所以對前端而言它只是一串亂碼.
不過我覺得用JWT當 토큰應該有 2個優點:
require 'jwt'
payload = {
first_name: 'Kevin',
last_name: 'Luo'
}
secret = "my secret"
token = JWT.encode payload, secret, 'HS256'
# "eyJhbGciOiJIUzI1NiJ9.eyJmaXJzdF9uYW1lIjoiS2V2aW4iLCJsYXN0X25hbWUiOiJMdW8ifQ.dZJnejsQ9cWs1hyOvCAij_Q4k87vfbQpeBIjgqYCrgs"
decoded_token = JWT.decode token, secret, true, { algorithm: 'HS256' }
# [{"first_name"=>"Kevin", "last_name"=>"Luo"}, {"alg"=>"HS256"}]
require 'jwt'
exp = Time.now.to_i + 3600 # 1 hour
exp_payload = { data: payload, exp: exp }
token = JWT.encode exp_payload, secret, 'HS256'
# "eyJhbGciOiJIUzI1NiJ9.eyJkYXRhIjp7ImZpcnN0X25hbWUiOiJLZXZpbiIsImxhc3RfbmFtZSI6Ikx1byJ9LCJleHAiOjE2MTM4ODU4MjF9.1_NIKXDnBVz1G6Li7_CZbcDwIk5AFaOsreK7BFDS13Q"
begin
decoded_token = JWT.decode token, secret, true, { algorithm: ‘HS256’ }
# [{"data"=>{"first_name"=>"Kevin", "last_name"=>"Luo"}, "exp"=>1613885821}, {"alg"=>"HS256"}]
rescue JWT::ExpiredSignature
# 過期
end
JWT除了可以讓 2台有共同 비밀.的電腦可互傳確認不會被篡改的資料外,
最常見的情境應該就是後端 미국 석유 학회使用者登入後發給前端的 토큰了吧.
會用 미국 석유 학회的 청원的 타이틀中所帶的 토큰 머니來判斷來源是否可以取用該 미국 석유 학회
雖然拿 JWT當 토큰 머니因為前端應該是不會有共有的 비밀.
沒辦法去驗證訊息,所以對前端而言它只是一串亂碼.
不過我覺得用JWT當 토큰應該有 2個優點:
JWT的分享到此囉 : )
Reference
이 문제에 관하여(見令如見人,介紹 JWT), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/kevinluo201/jwt-27ng텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)