登錄 token 前後端分離之JWT用戶認證.txt

登錄 token 前後端分離之JWT用戶認證.txt
參考:https://www.jianshu.com/p/180a870a308a
https://blog.csdn.net/qq_39314932/article/details/88356747
https://segmentfault.com/a/1190000019938678

一、Json Web Token(JWT)
適用場景
1、用於向Web應用傳遞一些非敏感信息。例如完成加好友、下訂單的操作等等。
2、用於設計用戶認證和授權系統。
3、實現Web應用的單點登錄。

實例場景
在A用戶關注了B用戶的時候,系統發郵件給B用戶,
並且附有一個鏈接“點此關注A用戶”。
鏈接的地址:
https://your.awesome-app.com/make-friend/?from_user=B&target_user=A。
讓B用戶不用登錄就可以完成這個操作。

1.1.JWT 是一個開放標準(RFC 7519),
它定義了一種用於簡潔,自包含的用於通信雙方之間以 JSON 對象的形式安全傳遞信息的方法。
JWT 可以使用 HMAC 算法或者是 RSA 的公鑰密鑰對進行簽名。
它具備兩個特點:
簡潔(Compact)
可以通過URL, POST 參數或者在 HTTP header 發送,因爲數據量小,傳輸速度快
自包含(Self-contained)
負載中包含了所有用戶所需要的信息,避免了多次查詢數據庫

1.2.JWT 組成
Header(頭部),Payload(負載),Signature(簽名)。
1.2.1.Header
描述 JWT 最基本的信息,例如,其類型及簽名所用的算法等。
通常如下:
{
  "alg": "HS256",
  "typ": "JWT"
}
注:
alg,簽名的算法(algorithm),默認是 HMAC SHA256(寫成 HS256);
typ,令牌(token)的類型(type),JWT令牌統一寫爲JWT。
用途:將 header 對象使用 Base64URL 方法編碼成字符串,組成 JWT 結構的第一部分。

1.2.2.Payload
用來存放實際需要傳遞的數據。JWT規定了7個官方字段,供選用。
例子:
{
  // 7個官方字段
  "jti": "1111", // JWT ID:編號
  "iss": "a.com", // issuer:簽發人
  "iat": "xxx", // Issued At: 簽發時間
  "nbf": "xxx", // Not Before:生效時間
  "exp": "1d", // expiration time:(必須設置)
  "sub": "test", // subject: 主題
  "aud": "xxx", // audience: 受衆
  // 可以定義私有字段
  "name": "John Doe",
  "admin": true
}
{
    "iss": "John Wu JWT",
    "iat": 1441593502,
    "exp": 1441594722,
    "aud": "www.example.com",
    "sub": "[email protected]",
    "from_user": "B",
    "target_user": "A"
}
注:
iss (issuer)   該JWT的簽發者
exp (expiration time)  過期時間(爲一個UNIX時間戳)
sub (subject)  該JWT所面向的用戶
aud (audience):    接受該JWT的一方
nbf (Not Before)   生效時間
iat (Issued At)    簽發時間
jti (JWT ID)   編號

它也使用 Base64URL 方法編碼成字符串,組成 JWT 結構的第二部分。
注:JWT 默認是不加密的,任何人都可以讀到,所以不要把祕密信息放在這個部分。

1.2.3.Signature(簽名)
對前兩部分的簽名,防止數據被篡改。
需要指定一個密鑰(secret)。
採用的公式:
Signature = header 中的簽名算法(base64UrlEncode(header) + '.' + base64UrlEncode(payload), secret)
JWT = Base64(Header) + "." + Base64(Payload) + "." + $Signature

將上面的兩個編碼後的字符串用點號連接在一起(頭部在前),就形成了,例如:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0
最後,我們將上面拼接完的字符串用 HS256 算法進行加密。
在加密的時候,我們還需要提供一個密鑰(secret)。
如果我們用 mystar 作爲密鑰的話,那麼就可以得到我們加密後的內容:
rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM
這一部分又叫做簽名。
後將這一部分簽名也拼接在被簽名的字符串後面,
我們就得到了完整的 JWT:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0.rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM
於是,我們就可以將郵件中的URL改成:
https://your.awesome-app.com/make-friend/?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0.rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM
然後使用 header 中指定的簽名算法(HS256)進行簽名。

1.2.4.簽名的目的
最後一步簽名的過程,實際上是對頭部、負載內容進行簽名,防止內容被竄改。
如果有人對頭部以及負載的內容解碼之後進行修改,再進行編碼,
最後加上之前的簽名組合形成新的JWT的話,
那麼服務器端會判斷出新的頭部和負載形成的簽名和JWT附帶上的簽名是不一樣的。
如果要對新的頭部和負載進行簽名,在不知道服務器加密時用的密鑰的話,得出來的簽名也是不一樣的。

1.3.JWT 使用
1.3.1.首先,前端通過Web表單將自己的用戶名和密碼發送到後端的接口。
這一過程一般是一個HTTP POST請求。
建議的方式是通過SSL加密的傳輸(https協議),從而避免敏感信息被嗅探。
1.3.2.後端驗證成功,根據上述方法生成 token,並返回給前端。
1.3.3.前端可以將返回的結果保存在localStorage或sessionStorage上,
退出登錄時前端刪除保存的JWT即可。
1.3.4.前端在每次請求時將JWT放入HTTP Header中的Authorization位。(解決XSS和XSRF問題)
1.3.5.後端檢查是否存在,如存在,驗證JWT的有效性。
例如,檢查簽名是否正確;檢查Token是否過期;檢查Token的接收方是否是自己(可選)。
1.3.6.驗證通過後,後端使用JWT中包含的用戶信息進行其他邏輯操作,返回相應結果。


1.4.JWT 的優勢
JWT方式將用戶狀態分散到了客戶端中,可以明顯減輕服務端的內存壓力。
除了用戶id之外,還可以存儲其他的和用戶相關的信息,
例如該用戶是否是管理員、用戶所在的分組等。
雖說JWT方式讓服務器有一些計算壓力(例如加密、編碼和解碼),
但是這些壓力相比磁盤存儲而言可能就不算什麼了。
具體是否採用,需要在不同場景下用數據說話。


1.5.總結
JWT的主要作用:
(一)可附帶用戶信息,後端直接通過JWT獲取相關信息。
(二)使用本地保存,通過HTTP Header中的 Authorization 位提交驗證。
可以放在 HTTP 請求頭 Authorization 字段中,還可以在 post 請求的時候放在請求數據裏。
但其實關於JWT存放到哪裏一直有很多討論,有人說存放到本地存儲,有人說存 cookie。
個人偏向於放在本地存儲。


1.6.JWT 的幾個特點
(1)JWT默認是不加密,但也是可以加密的。生成原始Token以後,可以用密鑰再加密一次。
(2)JWT不加密的情況下,不能將祕密數據寫入JWT。
     發送 JWT,要使用 https,不使用 https 的時候,JWT裏面不要寫入祕密數據。
(3)JWT不僅可以用於認證,也可以用於交換信息。有效使用 JWT,可以降低服務器查詢數據庫的次數。
(4)JWT的最大缺點是,由於服務器不保存session狀態,
     因此無法在使用過程中廢止某個token,或者更改token的權限。
     也就是說,一旦JWT簽發了,在到期之前就會始終有效,除非服務器部署額外的邏輯。
(5)JWT本身包含了認證信息,一旦泄露,任何人都可以獲得該令牌的所有權限。
     爲了減少盜用,JWT 的有效期應該設置得比較短。
     對於一些比較重要的權限,使用時應該再次對用戶進行認證。
(6)爲了減少盜用,JWT 不應該使用 HTTP 協議明碼傳輸,要使用 HTTPS 協議傳輸。
(7)便於傳輸,jwt的構成非常簡單,字節佔用很小,所以它是非常便於傳輸的。
(8)它不需要在服務端保存會話信息,所以它易於應用的擴展。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章