JWT(Json Web Token)
安全的在web應用間傳遞信息
JSON Web Token(以下簡稱JWT)是一個非常輕巧的規範。這個規範允許我們使用JWT在用戶和服務器之間傳遞安全可靠的信息。
來假想一下。用戶甲關注了用戶乙,系統發mail給用戶乙,並且附有一個連結"點此關注用戶甲"。連結的地址為:
上面的URL主要通過URL來描述,這樣作有一個弊端,必須要要求用戶乙先登錄。可不可以簡化這個流程,讓用戶乙部用登錄就可以完成這個操作,JWT就允許我們作到這點。
JWT的組成
一個JWT實際上就是一個字串,它由三部份組成,頭部、載荷以及簽名。
載荷(Payload)
我們繼續沿用上面假想的加好友情境,將這操作描述成一個JSON對象。其中添加了一些其它的信息,幫助今後收到這個JWT的服務器理解這個JWT。
這裡面前五個都是由JWT的標準所定義的。
iss:該JWT的簽發者
sub:該JWT所面向的用戶
aud:接收該JWT的一方
exp:什麼時候過期,這裡是一個Unix的timestamp
iat:在什麼時候簽發的
將上面的JSON對象進行[base64]編碼,可以得到下面的字串,這個字串我們將它稱作JWT的Payload。
如果你使用Node.js,可以用Node.js的包[ base64url ]來得到這個字串
PS:Base64是一種編碼,也就是說它是可以被翻譯回原來的樣子的,它並不是一種加密過程。
頭部(Header)
JWT還需要一個頭部,頭部用於描述關於該JWT的最基本的信息,例如其類型以及簽名所用的算法等,這也可以被看成一個JSON對象。
在這裡,我們說明了這是一個JWT,並且我們所用的簽名算法(後面會提到)是HS256算法。
我們將頭部也進行Base64編碼,出來的字串就是JWT的頭部了。
簽名
將上面兩個編碼字串用.
連接就形成了
最後,我們將上面拼接完的字串用HS256算法進行加密。在加密的時候,我們還需要個密鑰,假設我們用mystar
做為密鑰的話,那麼就可以得到我們加密後的內容
這就是簽名
最後將頭部、載荷以及簽名之間都用.
連接,我們就可以得到完整的JWT
於是我們就可以把剛剛那個加好友的URL改成下面這樣
這樣就安全的完成天加好友的操作了。
簽名的目的
最後一步簽名的過程,實際上是對頭部以及載荷內容進行簽名。一般而言,加密算法對於不同的輸入產生的輸出會不一樣。
所以,如果有人對頭部以及載荷的內容解碼之後進行修改,再進行編碼,那麼新的頭部和載荷的簽名和之前的簽名就將是不一樣的,而且如果不知道服務器加密的時候用的密鑰的話,得出來的簽名也一定會是不一樣的。
服務器應用在接受到JWT後,會首先對頭部和載荷的內容用同一算法再次簽名,那麼服務器應用是怎麼知道我們用的是哪一種算法呢?因為我們在JWT的頭部中已經用alg
指明了我們的加密算法了。
如果服務器應用對頭部和載荷再次以同樣方法簽名之後發現,自己計算出來的簽名和接受到的簽名不一樣,那麼就說明這個Token的內容被別人動過,我們將拒絕這個Token,跳出401錯誤頁面。
信息會暴露
所以,在JWT中,不應該在載荷裡面加入任何敏感的數據,在上面的例子中,我們傳輸的是用戶的UserID,這個實際上不是什麼敏感內容,一般情況下被知道也是安全的。
但是像密碼這樣的內容就不能被放在JWT中了。如果將用戶的密碼放在了JWT中,那麼遇到惡意的第三方就可以通過base64解碼很快的知道你的密碼了。
JWT的適用場景
我們可以看到,JWT適合用於向Web應用傳遞一些非敏感信息。例如在上面題到的完成加好友的操作,還有諸如下訂單的操作等等。
其實JWT還經常用於設計用戶認證和授權系統。甚至實現Web應用的單點登入(這個功能我在Laravel那本筆記有紀錄)。
Last updated
Was this helpful?