原文連接:medium.com/vandium-sof…html
在本文中,將解釋JSON Web Tokens(JWT)的基本原理以及使用緣由。 JWT 是確保應用程序信任和安全的重要部分。 JWT 容許以安全的方式表示諸如用戶數據之類的聲明。git
爲了解釋 JWT 如何工做,讓咱們從一個抽象的定義開始。github
JSON Web令牌(JWT)是一種 JSON 對象,在 RFC 7519 中定義爲在兩方之間表示一組信息的安全方式。 JWT 由頭部(header),負載(payload)和簽名(signature)組成。web
簡單地說,JWT只是一個具備如下格式的字符串:算法
header.payload.signature
複製代碼
應該注意,雙引號字符串被認爲是有效的 JSON 對象。json
爲了說明實際使用 JWT 的方式和緣由,咱們將使用一個簡單的示例(參見下圖)。 此示例中的三個不一樣的實體是用戶,應用程序服務器和身份驗證服務器。 驗證服務器將向用戶提供 JWT。 使用 JWT,用戶能夠安全地與應用程序通訊。安全
應用程序如何使用JWT驗證用戶的真實性bash
在該示例中,用戶首先使用認證服務器的登陸系統登陸認證服務器(例如,用戶名和密碼,Facebook登陸,Google登陸等)。 而後,身份驗證服務器建立 JWT並將其發送給用戶。 當用戶對應用程序進行 API 調用時,用戶將傳遞 JWT 以及 API 調用。 在這個實例中,應用程序服務器將能夠驗證傳入的 JWT 是不是由身份驗證服務器建立的(驗證過程將在稍後更詳細地說明)。當用戶使用附加的 JWT 進行API 調用時,應用程序可使用 JWT 來驗證該 API 調用是否來自通過身份驗證的用戶。服務器
如今,將更深刻地研究 JWT 自己及其構建和驗證的方式。ide
JWT 的 Header 部分包含有關如何計算 JWT 簽名的信息,是一個如下形式的 JSON 對象:
{
"typ": "JWT",
"alg": "HS256"
}
複製代碼
在上面的 JSON 中,「typ」鍵的值指定對象是JWT,「alg」鍵的值指定用於建立 JWT 簽名的算法。 在示例中,咱們使用 HMAC-SHA256算法(一種使用密鑰的散列算法)來計算簽名(在步驟3中會更詳細的介紹)。
JWT 的 payload 部分時是存儲在 JWT 內的數據。在咱們的示例中,身份驗證服務器建立一個JWT,其中存儲有用戶信息,特別是用戶ID。
{
"userId": "b08f86af-35da-48f2-8fab-cef3904660bd"
}
複製代碼
The data inside the payload is referred to as the 「claims」 of the token.
在咱們的示例中,咱們只將一個聲明放入 payload 中。 你能夠根據須要添加任意數量的聲明。JWT 規定了7個官方字段,供選用。
iss (issuer):簽發人
exp (expiration time):過時時間
sub (subject):主題
aud (audience):受衆
nbf (Not Before):生效時間
iat (Issued At):簽發時間
jti (JWT ID):編號
複製代碼
除了官方字段,你還能夠在這個部分定義私有字段。請記住,數據的大小將影響JWT的整體大小,這一般不是問題,但過大的 JWT 可能會對性能產生負面影響並致使延遲。
簽名使用如下僞代碼計算:
// signature algorithm
data = base64urlEncode( header ) + 「.」 + base64urlEncode( payload )
hashedData = hash( data, secret )
signature = base64urlEncode( hashedData )
複製代碼
該算法所作的是 base64url 對在步驟1和2中建立的header和payload進行編碼。而後,算法將獲得的編碼字符串用「點」(.)連在一塊兒。
在示例中,header 和 payload 被 base64url 編碼爲:
// header
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
// payload
eyJ1c2VySWQiOiJiMDhmODZhZi0zNWRhLTQ4ZjItOGZhYi1jZWYzOTA0NjYwYmQifQ
複製代碼
而後,在加入週期的編碼頭和編碼有效載荷上應用帶有密鑰的指定簽名算法,咱們獲得簽名所需的散列數據。 在咱們的例子中,這意味着在數據字符串上應用 HS256 算法,並將密鑰設置爲字符串「secret」,以獲取 hashedData字符串。 以後,經過base64url 編碼 hashedData 字符串,咱們獲得如下JWT簽名:
// signature
-xN_h82PHVTCMA9vdoHrcZxH-x5mb11y1537t3rGzcM
複製代碼
如今咱們已經建立了全部三個組件,咱們能夠建立JWT。 記住JWT的header.payload.signature結構,咱們只須要組合以上的三個部分,用點(.)分隔它們。
// JWT Token
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJiMDhmODZhZi0zNWRhLTQ4ZjItOGZhYi1jZWYzOTA0NjYwYmQifQ.-xN_h82PHVTCMA9vdoHrcZxH-x5mb11y1537t3rGzcM
複製代碼
你能夠嘗試經過 jwt.io 建立本身的JWT。
回到咱們的示例,身份驗證服務器如今能夠將此 JWT 發送給用戶。
要理解使用 JWT 的目的不是以任何方式隱藏或模糊數據,而是爲了證實發送的數據是由真實的來源建立的。
如前面的步驟所示,JWT 內的數據是通過編碼和簽名的,而不是加密的。 編碼數據的目的是轉換數據的結構。 簽名數據容許數據接收器驗證數據源的真實性。 所以,編碼和簽名數據不會保護數據。 另外一方面,加密的主要目的是保護數據並防止未經受權的訪問。 有關編碼和加密之間差別的更詳細說明,請參閱此文章。
因爲 JWT 僅被簽名和編碼,而且因爲 JWT 未加密,所以 JWT 不能保證敏感數據的安全性。
在咱們的示例中,咱們使用的是由 HS256 算法簽名的JWT,其中只有身份驗證服務器和應用服務器知道密鑰。當應用程序設置其身份驗證過程時,應用程序服務器從身份驗證服務器接收密鑰。因爲應用程序知道密鑰,當用戶對應用程序進行帶有 JWT 附加的 API 調用時,應用程序能夠執行與 JWT 上的步驟3相同的簽名算法。而後,應用程序能夠驗證從其本身的哈希操做得到的簽名是否與 JWT 自己上的簽名匹配(即,它與由認證服務器建立的 JWT 簽名匹配)。若是簽名匹配,則表示 JWT 有效,表示 API 調用來自可信源。不然,若是簽名不匹配,則表示收到的 JWT 無效,這多是對應用程序的潛在攻擊的指示。所以,經過驗證 JWT,應用程序在其自身和用戶之間添加了一層信任。
咱們瞭解了 JWT 是什麼,如何建立和驗證它們,以及如何使用它們來確保應用程序與其用戶之間的信任。這是瞭解 JWT 基礎知識及其有用之處的起點。 JWT 只是確保應用程序中的信任和安全性的難題之一。 應該注意,本文中描述的 JWT 身份驗證設置使用對稱密鑰算法(HS256)。你也能夠以相似的方式設置 JWT 身份驗證,除非使用非對稱算法(例如RS256),其中身份驗證服務器具備密鑰,而且應用程序服務器具備公鑰。查看此 Stack Overflow問題,瞭解使用對稱和非對稱算法之間差別的詳細分類。 還應該注意,JWT 應該經過 HTTPS 鏈接發送。擁有 HTTPS 有助於防止未經受權的用戶經過使用它來竊取所發送的 JWT,從而沒法攔截服務器和用戶之間的通訊。 此外,在 JWT 中設置較短的過時時間十分重要,這樣若是舊的 JWT 受到盜用,它們將被視爲無效而且不能再使用。
《IVWEB 技術週刊》 震撼上線了,關注公衆號:IVWEB社區,每週定時推送優質文章。