一、JWT簡介
1、什么是jwt
JWT(JSON WEB TOKEN):JSON網絡令牌,JWT是一個輕便的安全跨平台傳輸格式,定義了一個緊湊的自包含的方式在不同實體之間安全傳輸信息(JSON格式)。它是在Web環境下兩個實體之間傳輸數據的一項標准。實際上傳輸的就是一個字符串。廣義上講JWT是一個標准的名稱;狹義上JWT指的就是用來傳遞的那個token字符串。
2、jwt可以做什么
由於http協議是無狀態的,所以客戶端每次訪問都是新的請求。這樣每次請求都需要驗證身份,傳統方式是用session+cookie來記錄/傳輸用戶信息,而JWT就是更安全方便的方式。它的特點就是簡潔,緊湊和自包含,而且不占空間,傳輸速度快,而且有利於多端分離,接口的交互等等。
JWT是一種Token規范,主要面向的還是登錄、驗證和授權方向,當然也可以用只來傳遞信息。一般都是存在header里,也可以存在cookie里。
3、jwt使用場景
- Authorization (授權) : 這是使用JWT的最常見場景。一旦用戶登錄,后續每個請求都將包含JWT,允許用戶訪問該令牌允許的路由、服務和資源。單點登錄是現在廣泛使用的JWT的一個特性,因為它的開銷很小,並且可以輕松地跨域使用(有點像通關文牒)。
- Information Exchange (信息交換) : 對於安全的在各方之間傳輸信息而言,JSON Web Tokens無疑是一種很好的方式。因為JWT可以被簽名,例如,用公鑰/私鑰對,你可以確定發送人就是它們所說的那個人。另外,由於簽名是使用頭和有效負載計算的,您還可以驗證內容沒有被篡改。
- 其他

二、JWT組成
1、初識jwt
a、這是一個標准的jwt密文字符串,一般在項目中傳輸的就是這種格式的jwt。
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
eyJhdWQiOiIzN2Q4NWI0ZS0wN2EwLTRhNjctOTMyNi1jMjE3N2M0YWM1MDgiLCJwaG9uZSI6IjEyMzQ1Njc4OTAiLCJleHAiOjE2MjkxOTE4NzksImlhdCI6MTYyOTE5MTg0OX0. It3uim-1pwsZtKfpnXLqvo5nEjwyytPXiiyc6vJ12s8
b、這是一個明文狀態的jwt字符串。
{"alg":"HS256","typ":"JWT"}.
{"aud":"37d85b4e-07a0-4a67-9326-c2177c4ac508","phone":"1234567890","exp":1629191879,"iat":1629191849}.
{秘鑰}
2、JWT可以分為三個部分:
1、jwt的頭部(header)
jwt的頭部承載兩部分信息:
- 聲明類型,這里是jwt
- 聲明加密的算法 ,通常直接使用 HMAC SHA256
完整的頭部就像下面這樣的JSON:
{"alg":"HS256","typ":"JWT"}
然后將頭部進行base64加密(該加密是可以對稱解密的),構成了第一部分.
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
jwt的頭部除了默認有alg與typ字段外,也是可以添加自定義信息的,添加方式:
JWT.create().withHeader(map)
map中存放自定義信息就可以。
注意:自定義字段名不能是alg與typ,設置了也不會生效。
2、jwt的載荷(payload)
payload用來承載要傳遞的數據,它的json結構實際上是對JWT要傳遞的數據的聲明,這些聲明被JWT標准稱為claims(聲明),它的每個屬性鍵值對其實就是一個claim(聲明)。
JWT有三種聲明:
- Reserved claims(標准聲明)
- Private claims(私有聲明)
- public claims(公共聲明)
a、標准聲明:
JWT規定的標准聲明 (建議但不強制使用)。
- iss(Issuser):代表這個JWT的簽發主體;
- sub(Subject):代表這個JWT的主體,即它的所有人;
- aud(Audience):代表這個JWT的接收對象;
- exp(Expiration time):是一個時間戳,代表這個JWT的過期時間;
- nbf(Not Before):是一個時間戳,代表這個JWT生效的開始時間,意味着在這個時間之前驗證JWT是會失敗的;
- iat(Issued at):是一個時間戳,代表這個JWT的簽發時間;
- jti(JWT ID):是JWT的唯一標識,主要用來作為一次性token,從而回避重放攻擊。
b、私有聲明:
私有聲明是提供者和消費者所共同定義的聲明,一般不建議存放敏感信息,因為base64是對稱解密的,意味着該部分信息可以歸類為明文信息。
c、公共聲明:
公共的聲明可以添加任何的信息,一般添加用戶的相關信息或其他業務需要的必要信息.但不建議添加敏感信息,因為該部分在客戶端可解密。
定義一個payload:
{"aud":"37d85b4e-07a0-4a67-9326-c2177c4ac508","phone":"1234567890","exp":1629191879,"iat":1629191849}
然后將其進行base64加密,得到JWT的第二部分:
eyJhdWQiOiIzN2Q4NWI0ZS0wN2EwLTRhNjctOTMyNi1jMjE3N2M0YWM1MDgiLCJwaG9uZSI6IjEyMzQ1Njc4OTAiLCJleHAiOjE2MjkxOTE4NzksImlhdCI6MTYyOTE5MTg0OX0
3、jwt的簽證(signature)
這個簽證信息由三部分組成:
- header (base64后的)
- payload (base64后的)
- secret
這個部分需要base64加密后的header和base64加密后的payload使用.連接組成的字符串,加上secret后的組合字符串,再通過header中聲明的加密方式進行加密,然后就構成了jwt的第三部分。
secret = '秘鑰'
encodedString = base64(header) + '.' + base64(payload)
signature = HMACSHA256(encodedString, secret)
jwt = base64(header) + '.' + base64(payload) + '.' + signature
secret是保存在服務器端的,jwt的簽發生成也是在服務器端的,secret就是用來進行jwt的簽發和jwt的驗證,所以,它就是你服務端的私鑰,在任何場景都不應該流露出去。一旦客戶端得知這個secret, 那就意味着客戶端是可以自我簽發jwt了。