JSON Web Token(JWT)

什麼是JWT

Json web token(JWT)是爲了網絡應用環境間傳遞聲明而執行的一種基於JSON的開發標準(RFC 7519),該token被設計爲緊湊且安全的,特別適用於分佈式站點的單點登錄(SSO)場景。JWT的聲明通常被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便於從資源服務器獲取資源,也能夠增長一些額外的其它業務邏輯所必須的聲明信息,該token也可直接被用於認證,也可被加密。git

爲何用JWT

咱們知道http協議是無狀態的,一般咱們爲了進行用戶認證,流程大概以下:github

1.客戶端發送用戶名和密碼給服務器;
2.服務器接驗證經過後,會將當前會話(session)中保存用戶信息;
3.服務器向客戶端發送一個session_id做爲會話憑證,並寫入cookie;
4.用戶每次請求從cookie中獲取session_id併發送給服務器;
5.服務器驗證session_id,web

session認證的缺點:算法

  • 難以拓展 用戶認證以後,服務端作認證記錄,若是認證的記錄被保存在內存的話,這意味着用戶下次請求還必需要請求在這臺服務器上,這樣才能拿到受權的資源,這樣在分佈式的應用上,響應的限制了負載均衡器的能力,也意味着限制了應用的擴展性。json

  • CSRF 由於是基於cookie來進行用戶識別的,cookie若是被截獲,用戶就會很容易受到跨站請求僞造的攻擊。api

JWT原理

基於token的鑑權機制相似於http協議也是無狀態的,它不須要在服務端去保留用戶的認證信息或會話信息。這也就意味着機遇tokent認證機制的應用不須要去考慮用戶在哪一臺服務器登錄了,這就爲應用的擴展提供了便利。安全

  • 用戶使用帳戶和密碼請求服務器;
  • 服務器驗證用戶信息;
  • 服務器驗證經過後返回惟一token給客戶端;
  • 客戶端保存token,並每次請求帶上;
  • 服務器驗證token,並返回數據;

這個token必需要在每次請求時發送給服務器,它應該保存在請求頭中,另外,服務器要支持CORS(跨來源資源共享)策略,通常咱們在服務端這麼作就能夠了 Access-Control-Allow-Origin:*bash

JWT的構成

JWT是由三部分構成,將這三段信息文本用連接構成了JWT字符串。就像這樣服務器

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
eyJVc2VySWQiOjEyMywiVXNlck5hbWUiOiJhZG1pbiJ9.
Qjw1epD5P6p4Yy2yju3-fkq28PddznqRj3ESfALQy_U
複製代碼

第一部分咱們稱它爲頭部(header)第二部分咱們稱其爲載荷(payload,相似於飛機上承載的物品),第三部分是簽證(signature)cookie

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', {

headers: {
      'Authorization': 'Bearer ' + token
    }
  })
複製代碼

總結

  • 由於json的通用性,因此JWT是能夠跨語言支持的,像C#,JavaScript,NodeJS,PHP等許多語言均可以使用
  • 由於由了payload部分,因此JWT能夠在自身存儲一些其它業務邏輯所必要的非敏感信息
  • 便於傳輸,jwt的構成很是簡單,字節佔用很小,因此它是很是便於傳輸的
  • 它不須要在服務端保存會話信息,因此它易於應用的擴展
  • 不該該在jwt的payload部分存儲敏感信息,由於該部分是客戶端可解密的部分
  • 保護好secret私鑰。該私鑰很是重要
  • 若是能夠,請使用https協議

轉載地址: github.com/huzhao0316/…
相關文章
相關標籤/搜索