參考:JWT——概念、認證流程、結構、使用JWT_Guizy-CSDN部落格
一、什麼是JWT
JWT簡稱
JSON Web Token
,也就是通過JSON形式作為Web應用中的令牌,用于在各方之間安全地将資訊作為
JSON對象
傳輸。在資料傳輸過程中還可以完成
資料加密
、
簽名
等相關處理。
二、JWT能做什麼?
1、授權
這是使用JWT的最常見方案。一旦使用者登入,每個後續請求将包括JWT,進而允許使用者通路該令牌允許的路由,服務和資源。單點登入是當今廣泛使用JWT的一項功能,因為它的開銷很小并且可以在不同的域中輕松使用。
2、資訊交換
JSON Web Token是在各方之間安全地傳輸資訊的好方法。因為可以對JWT進行簽名(例如,使用公鑰/私鑰對),是以您可以確定發件人是他們所說的人。此外,由于簽名是使用标頭和有效負載計算的,是以您還可以驗證内容是否遭到篡改。
三、JWT工作流程

四、JWT結構
JWT令牌
=
Header.Payload.Signature
JWT令牌組成 :
- 1.Header
- 2.Payload
- 3.Signature
是以,JWT通常如下所示:xxxxx.yyyyy.zzzzz
1、Header
- 标頭通常由兩部分組成:令牌的類型(即JWT)和所使用的簽名算法,例如HMAC SHA256或RSA。它會使用
編碼Base64
第一部分`。組成 JWT 結構的
- 注意:Base64是一種編碼,也就是說,它是可以被翻譯回原來的樣子來的。它并不是一種加密過程。
如下面是一串token,我們解析一下:
eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJsUnpNWXVwemNZUm9iTnMyZnpqdEtMX3BNZGhSS0JIdnJfTDRHMWpuR3hnIn0
.eyJqdGkiOiJjNTdjOTkwYS01ZDY1LTRhNmItODUyMS1lZjc5NDViNmQ3OTkiLCJleHAiOjE2MzQxNDU5NjcsIm5iZiI6MCwiaWF0IjoxNjM0MTEwMTcwLCJpc3MiOiJodHRwOi8vaWFtYXV0aC5pYW10ZXN0LnByZC51aW1wY2xvdWQuY29tL2F1dGgvcmVhbG1zL2J1c2luZXNzIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6ImIyNTkwYzQ0LWM1MWItNDRkOS04NTQ3LTcwZDI2NTEwYzIxOSIsInR5cCI6IkJlYXJlciIsImF6cCI6InVpbXBjbG91ZC1mcm9udGVuZCIsIm5vbmNlIjoiNjVhODNkNzYtZTNiMy00NzhmLWFhMDktOTFmMTU5MzlkODNlIiwiYXV0aF90aW1lIjoxNjM0MTA5OTY3LCJzZXNzaW9uX3N0YXRlIjoiM2U1ZjRkNTUtMmY3Ni00NmMzLWJkNDEtNDhlNzljOWMwZGU2IiwiYWNyIjoiMCIsImFsbG93ZWQtb3JpZ2lucyI6WyIqIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJvcGVuaWQgcHJvZmlsZSBlbWFpbCIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmFtZSI6IueuoeeQhuWRmCDnrqEiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiIsImdpdmVuX25hbWUiOiLnrqHnkIblkZgiLCJsb2NhbGUiOiJ6aC1DTiIsImZhbWlseV9uYW1lIjoi566hIn0
.aIKWuiP9_ENFi_cQBKsMxhuQkU6kkE49xLwYQuFucsctiUaDOnVh45NJ9mFKUlqMIuEzGwihTQoyI2Te8VnmWsCvTzODZHufUQDSYDvnwCXm1R9XBLL4b8x63z_c9_G6In6xspyhzVse5N8BTlzm4Vro0t_5pUltbW5O0_rBKeZ_7aC6nPLR6CQpibR1FFQfoSJO_qavwNudZKKycX4PrIWDRobfeJAWUY-AA3YtNjqlm8s46bcVairHQc98CInvEgSohe7Hz-pkBqXmDKsrQmv-VwQ7G5-LE-IpIr3UAugdUoKeL3J0Z0O2pf4856QsIwYe2dInh22HyNJSBfp9Rw
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9,就是header,我們用base64解析一下,得到:
{
"alg": "RS256",
"typ": "JWT",
"kid": "lRzMYupzcYRobNs2fzjtKL_pMdhRKBHvr_L4G1jnGxg"
}
2、Payload
- 令牌的第二部分是有效負載,其中包含聲明。聲明是有關實體(通常是使用者)和其他資料的聲明(
)。同樣的,它會使用存放使用者資訊的
組成 JWT 結構的Base64 編碼
第二部分
{
"jti": "c57c990a-5d65-4a6b-8521-ef7945b6d799",
"exp": 1634145967,
"nbf": 0,
"iat": 1634110170,
"iss": "http://iamauth.iamtest.prd.uimpcloud.com/auth/realms/business",
"aud": "account",
"sub": "b2590c44-c51b-44d9-8547-70d26510c219",
"typ": "Bearer",
"azp": "uimpcloud-frontend",
"nonce": "65a83d76-e3b3-478f-aa09-91f15939d83e",
"auth_time": 1634109967,
"session_state": "3e5f4d55-2f76-46c3-bd41-48e79c9c0de6",
"acr": "0",
"allowed-origins": ["*"],
"realm_access": {
"roles": ["offline_access", "uma_authorization"]
},
"resource_access": {
"account": {
"roles": ["manage-account", "manage-account-links", "view-profile"]
}
},
"scope": "openid profile email",
"email_verified": false,
"name": "管理者 管",
"preferred_username": "admin",
"given_name": "管理者",
"locale": "zh-CN",
"family_name": "管"
}
3、Signature
前面兩部分都是使用 Base64 進行編碼的,即前端可以解開知道裡面的資訊。Signature 需要使用編碼後的 header 和 payload 以及我們提供的一個密鑰,然後使用 header 中指定的簽名算法(HS256)進行簽名。簽名的作用是保證 JWT 沒有被篡改過
base64(header) . base64(payload) . "#**[email protected]"(秘鑰) -----> 組成 Signature
WT令牌 = base64(header) . base64(payload) . Signature
eg :
假如我們的JWT令牌傳回給用戶端了, 結構為base64(header).base64(payload).aaaaa, aaaaa是簽名, 由base64(header) . base64(payload) . 密鑰生成的, 用戶端此時拿到了這個Token;
jwt會先驗簽, 用戶端拿到token去請求資料, 首先服務端會先将該token的Signature和aaaaa作比對, 如果确實相同, 則該令牌是正确的;
這種做法就是為了防止篡改資料, 如果修改了header, payload, 生成的Signature都和服務端的對不上, 就會驗證該令牌是非法的;
簽名目的
最後一步簽名的過程,實際上是對頭部以及負載内容進行簽名,防止内容被竄改。如果有人對頭部以及負載的内容解碼之後進行修改,再進行編碼,最後加上之前的簽名組合形成新的JWT的話,那麼伺服器端會判斷出新的頭部和負載形成的簽名和JWT附帶上的簽名是不一樣的。如果要對新的頭部和負載進行簽名,在不知道伺服器加密時用的密鑰的話,得出來的簽名也是不一樣的。
資訊安全問題
在這裡大家一定會問一個問題:Base64是一種編碼,是可逆的,那麼我的資訊不就被暴露了嗎?
是的。是以,在JWT中,不應該在負載裡面加入任何敏感的資料。在上面的例子中,我們傳輸的是使用者的User ID。這個值實際上不是什麼敏感内容,一般情況下被知道也是安全的。但是像密碼這樣的内容就不能被放在JWT中了。如果将使用者的密碼放在了JWT中,那麼懷有惡意的第 三方通過Base64解碼就能很快地知道你的密碼了。是以JWT适合用于向Web應用傳遞一些非敏感資訊。JWT還經常用于設計使用者認證和授權系統,甚至實作Web應用的單點登入。