閱讀結束后,可以參考本人另一篇文章進行Springboot整合JWT:
https://www.cnblogs.com/code-duck/p/13485236.html
1.什么是JWT
json web token(JWT)是一個開放標准(rfc7519),它定義了一種緊湊的、自包含的方式,用於在各方之間以JSON對象安全地傳輸信息。它是以JSON形式作為Web應用中的令牌,用於在各方之間安全地將信息作為JSON對象傳輸。在數據傳輸過程中還可以完成數據加密、簽名等相關處理。
2.JWT能做什么
授權
這是使用JWT的最常見方案。一旦用戶登錄,每個后續請求將包括JWT,從而允許用戶訪問該令牌允許的路由,服務和資源。單點登錄是當今廣泛使用JWT的一項功能,因為它的開銷很小並且可以在不同的域中輕松使用。
信息交換
JSON Web Token是在各方之間安全地傳輸信息的好方法。因為可以對JWT進行簽名(例如,使用公鑰/私鑰對),所以您可以確保發件人是他們所說的人。此外,由於簽名是使用標頭和有效負載計算的,因此您還可驗證內容是否遭到篡改。
3.Session認證與JWT認證的區別
基於傳統的Session認證策略
1.認證方式
http協議本身是一種無狀態的協議
,而這就意味着如果用戶向我們的應用提供了用戶名和密碼來進行用戶認證,那么下一次請求時,用戶還要再一次進行用戶認證才行。
因為根據http協議,我們並不能知道是哪個用戶發出的請求,所以為了讓我們的應用能識別是哪個用戶發出的請求,我們只能在服務器存儲一份用戶登錄的信息,這份登錄信息(sessionId)會在響應時傳遞給瀏覽器,告訴其保存為cookie,以便下次請求時發送給我們的應用,這樣我們的應用就能識別請求來自哪個用戶了,這就是傳統的基於session認證。
2.認證流程
3.Session認證的問題
-
每個用戶經過我們的應用認證之后,我們的應用都要在服務端做一次記錄,以方便用戶下次請求的鑒別,通常而言session都是保存在內存中,而隨着認證用戶的增多,服務端的開銷會明顯增大
-
用戶認證之后,服務端做認證記錄,如果認證的記錄被保存在內存中的話,這意味着用戶下次請求還必須要請求在這台服務器上,這樣才能拿到授權的資源,這樣在分布式的應用上,相應的限制了負載均衡器的能力。這也意味着限制了應用的擴展能力。
-
因為是基於cookie來進行用戶識別的, cookie如果被截獲,用戶就會很容易受到跨站請求偽造的攻擊。
-
在前后端分離系統中就更加痛苦!也就是說前后端分離在應用解耦后增加了部署的復雜性。
- 通常用戶一次請求就要轉發多次。如果用session 每次攜帶sessionid 到服務器,服務器還要查詢用戶信息。同時如果用戶很多。這些信息存儲在服務器內存中,給服務器增加負擔。
- CSRF(跨站偽造請求攻擊)攻擊,session是基於cookie進行用戶識別的, cookie如果被截獲,用戶就會很容易受到跨站請求偽造的攻擊。
- sessionid 就是一個特征值,表達的信息不夠豐富。不容易擴展。而且如果你后端應用是多節點部署。那么就需要實現session共享機制。 不方便集群應用。
基於JWT認證的策略
1.認證流程
-
首先,前端通過Web表單將自己的用戶名和密碼發送到后端的接口。這一過程一般是一個HTTP POST請求。建議的方式是通過SSL加密的傳輸(https協議),從而避免敏感信息被嗅探。
-
后端核對用戶名和密碼成功后,將用戶的id等其他信息作為JWT Payload(負載),將其與頭部分別進行Base64編碼拼接后簽名,形成一個JWT(Token)。形成的JWT就是一個形同xxx.yyy.zzz的字符串。
即token = head.payload.singurater
-
后端將JWT字符串作為登錄成功的返回結果返回給前端。前端可以將返回的結果保存在localStorage或sessionStorage上,退出登錄時前端刪除保存的JWT即可。
-
前端在每次請求時將JWT放入HTTP Header中的Authorization位。(解決XSS和XSRF問題) HEADER
-
后端檢查是否存在,如存在驗證JWT的有效性。例如,檢查簽名是否正確;檢查Token是否過期;檢查Token的接收方是否是自己(可選)。
-
驗證通過后后端使用JWT中包含的用戶信息進行其他邏輯操作,返回相應結果。
2.jwt優勢
-
簡潔(Compact): 可以通過URL,POST參數或者在HTTP header發送,因為數據量小,傳輸速度也很快
-
自包含(Self-contained):負載中包含了所有用戶所需要的信息,避免了多次查詢數據庫
-
因為Token是以JSON加密的形式保存在客戶端的,所以JWT是跨語言的,原則上任何web形式都支持。
-
不需要在服務端保存會話信息,特別適用於分布式微服務。
4.JWT的結構
令牌組成
- 1.標頭(Header)
- 2.有效載荷(Payload)
- 3.簽名(Signature)
因此,JWT通常如下所示:xxxxx.yyyyy.zzzzz 也就是 Header.Payload.Signature
Header的組成信息
-
標頭通常由兩部分組成:
令牌的類型(即JWT)和所使用的簽名算法
,例如HMAC SHA256或RSA。它會使用 Base64 編碼組成 JWT 結構的第一部分。 -
注意:Base64是一種編碼,也就是說,它是可以被翻譯回原來的樣子來的。它並不是一種加密過程。
// header的組成信息
{
"alg": "HS256",
"typ": "JWT"
}
Payload組成信息
令牌的第二部分是有效負載,其中包含聲明。聲明是有關實體(通常是用戶信息)和其他數據的聲明。同樣的,它會使用 Base64 編碼組成 JWT 結構的第二部分
// payload組成信息
{
"id": "823",
"name": "Code Duck",
"role": "admin"
}
Signature的組成信息
header和payload
都是使用 Base64 進行編碼的,即前端可以解開知道里面的信息。Signature 需要使用編碼后的 header 和 payload 以及我們自己的一個密鑰
,然后使用 header 中指定的簽名算法(HS256)進行簽名。簽名的作用是保證 JWT 沒有被篡改過。
例如:HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret );
# 簽名目的
- 最后一步簽名的過程,實際上是對頭部以及負載內容進行簽名,防止內容被竄改。如果有人對頭部以及負載的內容解碼之后進行修改,再進行編碼,最后加上之前的簽名組合形成新的JWT的話,那么服務器端會判斷出新的頭部和負載形成的簽名和JWT附帶上的簽名是不一樣的。如果要對新的頭部和負載進行簽名,在不知道服務器加密時用的密鑰的話,得出來的簽名也是不一樣的。
# 信息安全問題
- 在這里大家一定會問一個問題:Base64是一種編碼,是可逆的,那么我的信息不就被暴露了嗎?
- 是的。所以,在JWT中,不應該在負載里面加入任何敏感的數據。在上面的例子中,我們傳輸的是用戶的User ID。這個值實際上不是什么敏感內容,一般情況下被知道也是安全的。但是像密碼這樣的內容就不能被放在JWT中了。如果將用戶的密碼放在了JWT中,那么懷有惡意的第三方通過Base64解碼就能很快地知道你的密碼了。因此JWT適合用於向Web應用傳遞一些非敏感信息。JWT還經常用於設計用戶認證和授權系統,甚至實現Web應用的單點登錄。
以上三部分進行整合
JWT的真實面目:
(Header)
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
(payLoad)
eyJyb2xlIjoiZW1wbG95ZWUiLCJpZCI6IjQiLCJleHAiOjE1OTcxMjc3NjUsInVzZXJuYW1lIjoiamFzb24ifQ.
(Signature)
WxIiTf7V4UaboMONu0UpPu-uQSuDQFZqepKKxLstnaU
👇形象解釋
- JWT令牌是三個由點分隔的Base64-URL字符串,可以在HTML和HTTP環境中輕松傳遞這些字符串,與基於XML的標准(例如SAML)相比,它更緊湊。
- 簡潔(Compact),可以通過URL, POST 參數或者在 HTTP header 發送,因為數據量小,傳輸速度快
- 自包含(Self-contained),負載中包含了所有用戶所需要的信息,避免了多次查詢數據庫