什麼是JWT
Json web token(JWT)是為了網絡應用環境間傳遞聲明而執行的一種基於JSON的開發標準(RFC 7519),該token被設計為緊湊且安全的,特別適用於分佈式站點的單點登陸(SSO)場景。JWT的聲明一般被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便於從資源服務器獲取資源,也可以增加一些額外的其它業務邏輯所必須的聲明信息,該token也可直接被用於認證,也可被加密。
為什麼用JWT
我們知道http協議是無狀態的,通常我們為了進行用戶認證,流程大概如下:
- 客戶端發送用戶名和密碼給服務器;
- 服務器接驗證通過後,會將當前會話(session)中保存用戶信息;
- 服務器向客戶端發送一個session_id作為會話憑證,並寫入cookie;
- 用戶每次請求從cookie中獲取session_id併發送給服務器;
- 服務器驗證session_id,查詢用戶信息;
session認證的缺點:
- 難以拓展
用戶認證之後,服務端做認證記錄,如果認證的記錄被保存在內存的話,這意味著用戶下次請求還必須要請求在這臺服務器上,這樣才能拿到授權的資源,這樣在分佈式的應用上,響應的限制了負載均衡器的能力,也意味著限制了應用的擴展性。
- CSRF 因為是基於cookie來進行用戶識別的,cookie如果被截獲,用戶就會很容易受到跨站請求偽造的攻擊。
JWT原理
基於token的鑑權機制類似於http協議也是無狀態的,它不需要在服務端去保留用戶的認證信息或會話信息。這也就意味著機遇tokent認證機制的應用不需要去考慮用戶在哪一臺服務器登陸了,這就為應用的擴展提供了便利。
- 用戶使用賬戶和密碼請求服務器;
- 服務器驗證用戶信息;
- 服務器驗證通過後返回唯一token給客戶端;
- 客戶端保存token,並每次請求帶上;
- 服務器驗證token,並返回數據;
這個token必須要在每次請求時發送給服務器,它應該保存在請求頭中,另外,服務器要支持CORS(跨來源資源共享)策略,一般我們在服務端這麼做就可以了 Access-Control-Allow-Origin:*
JWT的構成
JWT是由三部分構成,將這三段信息文本用鏈接構成了JWT字符串。就像這樣
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
eyJVc2VySWQiOjEyMywiVXNlck5hbWUiOiJhZG1pbiJ9.
Qjw1epD5P6p4Yy2yju3-fkq28PddznqRj3ESfALQy_U
第一部分我們稱它為頭部(header)第二部分我們稱其為載荷(payload,類似於飛機上承載的物品),第三部分是簽證(signature)
什麼是JWT
Json web token(JWT)是為了網絡應用環境間傳遞聲明而執行的一種基於JSON的開發標準(RFC 7519),該token被設計為緊湊且安全的,特別適用於分佈式站點的單點登陸(SSO)場景。JWT的聲明一般被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便於從資源服務器獲取資源,也可以增加一些額外的其它業務邏輯所必須的聲明信息,該token也可直接被用於認證,也可被加密。
為什麼用JWT
我們知道http協議是無狀態的,通常我們為了進行用戶認證,流程大概如下:
- 客戶端發送用戶名和密碼給服務器;
- 服務器接驗證通過後,會將當前會話(session)中保存用戶信息;
- 服務器向客戶端發送一個session_id作為會話憑證,並寫入cookie;
- 用戶每次請求從cookie中獲取session_id併發送給服務器;
- 服務器驗證session_id,查詢用戶信息;
session認證的缺點:
- 難以拓展
用戶認證之後,服務端做認證記錄,如果認證的記錄被保存在內存的話,這意味著用戶下次請求還必須要請求在這臺服務器上,這樣才能拿到授權的資源,這樣在分佈式的應用上,響應的限制了負載均衡器的能力,也意味著限制了應用的擴展性。
- CSRF 因為是基於cookie來進行用戶識別的,cookie如果被截獲,用戶就會很容易受到跨站請求偽造的攻擊。
JWT原理
基於token的鑑權機制類似於http協議也是無狀態的,它不需要在服務端去保留用戶的認證信息或會話信息。這也就意味著機遇tokent認證機制的應用不需要去考慮用戶在哪一臺服務器登陸了,這就為應用的擴展提供了便利。
- 用戶使用賬戶和密碼請求服務器;
- 服務器驗證用戶信息;
- 服務器驗證通過後返回唯一token給客戶端;
- 客戶端保存token,並每次請求帶上;
- 服務器驗證token,並返回數據;
這個token必須要在每次請求時發送給服務器,它應該保存在請求頭中,另外,服務器要支持CORS(跨來源資源共享)策略,一般我們在服務端這麼做就可以了 Access-Control-Allow-Origin:*
JWT的構成
JWT是由三部分構成,將這三段信息文本用鏈接構成了JWT字符串。就像這樣
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
eyJVc2VySWQiOjEyMywiVXNlck5hbWUiOiJhZG1pbiJ9.
Qjw1epD5P6p4Yy2yju3-fkq28PddznqRj3ESfALQy_U
第一部分我們稱它為頭部(header)第二部分我們稱其為載荷(payload,類似於飛機上承載的物品),第三部分是簽證(signature)
Header
JWT的頭部承載的兩部分信息:
- 聲明類型,這裡是jwt
- 聲明加密的算法,通常直接使用HMAC SHA256
{
'typ':'JWT',
'alg':'HS256'
}
然後將頭部進行base64加密(該加密是可以對稱解密的),構成了第一部分
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
plyload
Payload 部分也是一個 JSON 對象,用來存放實際需要傳遞的數據。JWT 規定了7個官方字段,供選用。
- iss (issuer):簽發人
- exp (expiration time):過期時間
- sub (subject):主題
- aud (audience):受眾
- nbf (Not Before):生效時間
- iat (Issued At):簽發時間
- jti (JWT ID):編號
Signature
Signature 部分是對前兩部分的簽名,防止數據篡改。
首先,需要指定一個密鑰(secret)。這個密鑰只有服務器才知道,不能洩露給用戶。然後,使用 Header 裡面指定的簽名算法(默認是 HMAC SHA256),按照下面的公式產生簽名。
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
注意:secret是保存在服務器端的,jwt的簽發也是在服務端的,secret就是用來進行jwt的簽發和jwt的驗證,所以它就是你服務端的私鑰,在任何場景都不應該流露出去,一旦客戶端得知這個secret,那就意味著客戶端可以自我簽發jwt了
一般是在請求頭裡加入Authorization,並加上Bearer標註:
fetch('api/user/1', {
fetch('api/user/1', {
headers: {
'Authorization': 'Bearer ' + token
}
})
總結
- 因為json的通用性,所以JWT是可以跨語言支持的,像C#,JavaScript,NodeJS,PHP等許多語言都可以使用
- 因為由了payload部分,所以JWT可以在自身存儲一些其它業務邏輯所必要的非敏感信息
- 便於傳輸,jwt的構成非常簡單,字節佔用很小,所以它是非常便於傳輸的
- 它不需要在服務端保存會話信息,所以它易於應用的擴展
- 不應該在jwt的payload部分存儲敏感信息,因為該部分是客戶端可解密的部分
- 保護好secret私鑰。該私鑰非常重要
- 如果可以,請使用https協議
希望本文能幫助到您!
點贊+轉發,讓更多的人也能看到這篇內容(收藏不點贊,都是耍流氓-_-)
關注 {我},享受文章首發體驗!
每週重點攻克一個前端技術難點。更多精彩前端內容私信 我 回覆“教程”!
原文鏈接:https://github.com/huzhao0316/articals/wiki/JSON-Web-Token%EF%BC%88JWT%EF%BC%89