1. 程式人生 > >JWT(JSON Web Token)原理簡介

JWT(JSON Web Token)原理簡介

oem 相關 部分 bsp process post tis 輸入 檢查

原文:http://www.fengchang.cc/post/114

參考了一下這篇文章:https://medium.com/vandium-software/5-easy-steps-to-understanding-json-web-tokens-jwt-1164c0adfcec

原理說的非常清楚。總結如下:

首先這個先說這個東西是什麽,幹什麽用的,一句話說:就是這是一種認證機制,讓後臺知道請求是來自於受信的客戶端。

那麽從這個角度而言,這個東西跟瀏覽器的cookie是一個作用,好比我在一個網站登錄了,就可以往這個網站發送restful請求,請求的同時會捎帶上cookie,後臺檢查這個cookie發現你是合法的,才響應你的請求。

只不過這裏JWT的原理不同,但基本上最頂層的原理還是非常簡單:

技術分享圖片

這個圖中有三個主體: user, application server和authentication server

非常常見的一個架構,首先用戶需要 通過登錄等手段向authentication server發送一個認證請求,authentication會返回給用戶一個JWT(這個JWT的具體內容格式是啥後面會說,先理解成一個簡單的字符串好了)

此後用戶向application server發送的所有請求都要捎帶上這個JWT,然後application server會驗證這個JWT的合法性,驗證通過則說明用戶請求時來自合法守信的客戶端。

下面簡單說一下這個JWT的格式,十分簡單,就是一個三部分組成的字符串:

技術分享圖片

下面一部分一部分來講:

header, 一個例子是:

技術分享圖片

非常簡單,typ顧名思義就是type的意思,例如上面這裏就指明是JWT的類型。alg顧名思義是algorithm的意思,指代一個加密算法,例如上面指代HS256(HMAC-SHA256),這個算法會在生成第三部分signature的時候用到。

payload,一個例子是:

技術分享圖片

這部分的本質是用戶數據,怎麽理解呢,就是JWT的目的是認證身份來源,那麽你是不是得自報家門我是誰呢?所以總得往裏塞點跟用戶相關的信息吧,例如這裏就是userId

signature,一個例子是:

技術分享圖片

signature顧名思義就是簽名,簽名一般就是用一些算法生成一個能夠認證身份的字符串,具體算法就是上面表示的,也比較簡單,不贅述,唯一說明的一點是上面hash方法用到了一個secret,這個東西需要application server和authentication server雙方都知道,相當於約好了同一把驗證的鑰匙,最終才好做認證。

至此,三個部分,都解釋完了,那麽按照header.payload.signature這個格式串起來就行了,串之前註意,header和payload也要做一個base64url encoded的轉換。那麽最終拼出來的一個例子是:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJiMDhmODZhZi0zNWRhLTQ4ZjItOGZhYi1jZWYzOTA0NjYwYmQifQ.-xN_h82PHVTCMA9vdoHrcZxH-x5mb11y1537t3rGzcM

再次強調一點,別看上面做了那麽多hash,其實目的不在加密保護數據,而是為了認證來源,認證來源,認證來源。JWT不保證數據不泄露,因為JWT的設計目的就不是數據加密和保護。

最後再解釋一下application server如何認證用戶發來的JWT是否合法,首先application server 和 authentication server必須要有個約定,例如雙方同時知道加密用的secret(這裏假設用的就是簡單的對稱加密算法),那麽在applicaition 收到這個JWT是,就可以利用JWT前兩段(別忘了JWT是個三段的拼成的字符串哦)數據作為輸入,用同一套hash算法和同一個secret自己計算一個簽名值,然後把計算出來的簽名值和收到的JWT第三段比較,如果相同則認證通過,如果不相同,則認證不通過。就這麽簡單,當然,上面是假設了這個hash算法是對稱加密算法,其實如果用非對稱加密算法也是可以的,比方說我就用非對稱的算法,那麽對應的key就是一對,而非一個,那麽一對公鑰+私鑰可以這樣分配:私鑰由authentication server保存,公鑰由application server保存,application server驗證的時候,用公鑰解密收到的signature,這樣就得到了header和payload的拼接值,用這個拼接值跟前兩段比較,相同就驗證通過。總之,方法略不同,但大方向完全一樣。

提兩個best practice:

1. 發送JWT要用https,原因前面說了,JWT本身不保證數據安全

2.JWT的payload中設置expire時間,為什麽要這樣做其實跟cookie為什麽要設置過期時間一樣,都是為了安全。

JWT(JSON Web Token)原理簡介