Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
者:古時(shí)的風(fēng)箏
原文鏈接:https://www.cnblogs.com/fengzheng/p/13527425.html
JWT 全稱是 JSON Web Token,是目前非常流行的跨域認(rèn)證解決方案,在單點(diǎn)登錄場(chǎng)景中經(jīng)常使用到。
有些人覺得它非常好用,用了它之后就不用在服務(wù)端借助 redis 實(shí)現(xiàn)認(rèn)證過(guò)程了,但是,還有一部分人認(rèn)為它生來(lái)就有缺陷,根本不能用。
這是為什么呢?
你平時(shí)用過(guò)那么多網(wǎng)站和 APP,其中有很多都是需要登錄的吧,那咱們就選一個(gè)場(chǎng)景出來(lái)說(shuō)說(shuō)。
以一個(gè)電商系統(tǒng)為例,如果你想要下單,首先需要注冊(cè)一個(gè)賬號(hào),擁有了賬號(hào)之后,需要輸入用戶名(比如手機(jī)號(hào)或郵箱)、密碼完成登錄過(guò)程。之后你在一段時(shí)間內(nèi)再次進(jìn)入系統(tǒng),是不需要輸入用戶名和密碼的,只有在連續(xù)長(zhǎng)時(shí)間不登錄的情況下(例如一個(gè)月沒登錄過(guò))訪問(wèn)系統(tǒng),才需要再次輸入用戶名和密碼。
對(duì)于那些使用頻率很高的網(wǎng)站或應(yīng)用,通常是很長(zhǎng)時(shí)間都不需要輸入密碼的,以至于你在換了一臺(tái)電腦或者一部手機(jī)之后,一些經(jīng)常使用的網(wǎng)站或 APP 的密碼都不記得了。
早期互聯(lián)網(wǎng)以 web 為主,客戶端是瀏覽器 ,所以 Cookie-Session 方式是早期最常用的認(rèn)證方式,直到現(xiàn)在,一些 web 網(wǎng)站依然用這種方式做認(rèn)證。
認(rèn)證過(guò)程大致如下:
但是為什么說(shuō)它是傳統(tǒng)的認(rèn)證方式,因?yàn)楝F(xiàn)在人手一部智能手機(jī),很多人都不用電腦,平時(shí)都是使用手機(jī)上的各種 APP,比如淘寶、拼多多等。
在這種潮流之下,傳統(tǒng)的 Cookie-Session 就遇到了一些問(wèn)題:
1、首先,Cookie-Session 只能在 web 場(chǎng)景下使用,如果是 APP 呢,APP 可沒有地方存 cookie。
現(xiàn)在的產(chǎn)品基本上都同時(shí)提供 web 端和 APP 兩種使用方式,有點(diǎn)產(chǎn)品甚至只有 APP。
2、退一萬(wàn)步說(shuō),你做的產(chǎn)品只支持 web,也要考慮跨域問(wèn)題, 但Cookie 是不能跨域的。
拿天貓商城來(lái)說(shuō),當(dāng)你進(jìn)入天貓商城后,會(huì)看到頂部有天貓超市、天貓國(guó)際、天貓會(huì)員這些菜單。而點(diǎn)擊這些菜單都會(huì)進(jìn)入不同的域名,不同的域名下的 cookie 都是不一樣的,你在 A 域名下是沒辦法拿到 B 域名的 cookie 的,即使是子域也不行。
3、如果是分布式服務(wù),需要考慮 Session 同步問(wèn)題。
現(xiàn)在的互聯(lián)網(wǎng)網(wǎng)站和 APP 基本上都是分布式部署,也就是服務(wù)端不止一臺(tái)機(jī)器。當(dāng)某個(gè)用戶在頁(yè)面上進(jìn)行登錄操作后,這個(gè)登錄動(dòng)作必定是請(qǐng)求到了其中某一臺(tái)服務(wù)器上。你的身份信息得保存下來(lái)吧,傳統(tǒng)方式就是存 Session。
接下來(lái),問(wèn)題來(lái)了。你訪問(wèn)了幾個(gè)頁(yè)面,這時(shí),有個(gè)請(qǐng)求經(jīng)過(guò)負(fù)載均衡,路由到了另外一臺(tái)服務(wù)器(不是你登錄的那臺(tái))。當(dāng)后臺(tái)接到請(qǐng)求后,要檢查用戶身份信息和權(quán)限,于是接口開始從從 Session 中獲取用戶信息。但是,這臺(tái)服務(wù)器不是當(dāng)時(shí)登錄的那臺(tái),并沒存你的 Session ,這樣后臺(tái)服務(wù)就認(rèn)為你是一個(gè)非登錄的用戶,也就不能給你返回?cái)?shù)據(jù)了。
所以,為了避免這種情況的發(fā)生,就要做 Session 同步。一臺(tái)服務(wù)器接收到登錄請(qǐng)求后,在當(dāng)前服務(wù)器保存 Session 后,也要向其他幾個(gè)服務(wù)器同步。
4、cookie 存在 CSRF(跨站請(qǐng)求偽造)的風(fēng)險(xiǎn)。 跨站請(qǐng)求偽造,是一種挾制用戶在當(dāng)前已登錄的Web應(yīng)用程序上執(zhí)行非本意的操作的攻擊方法。CSRF 利用的是網(wǎng)站對(duì)用戶網(wǎng)頁(yè)瀏覽器的信任。簡(jiǎn)單地說(shuō),是攻擊者通過(guò)一些技術(shù)手段欺騙用戶的瀏覽器去訪問(wèn)一個(gè)自己曾經(jīng)認(rèn)證過(guò)的網(wǎng)站并運(yùn)行一些操作(比如購(gòu)買商品)。由于瀏覽器曾經(jīng)認(rèn)證過(guò),所以被訪問(wèn)的網(wǎng)站會(huì)認(rèn)為是真正的用戶發(fā)起的操作。
比如說(shuō)我是一個(gè)黑客,我發(fā)現(xiàn)你經(jīng)常訪問(wèn)的一個(gè)技術(shù)網(wǎng)站存在 CSRF 漏洞。發(fā)布文章支持 html 格式,進(jìn)而我在 html 中加入一些危險(xiǎn)內(nèi)容,例如
<img src="http://www.examplebank.com/withdraw?account=Alice&amount=1000&for=Badman">
假設(shè) src 指向的地址是一個(gè)你平時(shí)用的購(gòu)物網(wǎng)站的付款地址(當(dāng)然只是舉例,真正的攻擊可沒這么簡(jiǎn)單),如果你之前登錄過(guò)并且標(biāo)識(shí)你身份信息的 cookie 已經(jīng)保存下來(lái)了。當(dāng)你刷到我發(fā)布的這篇文章的時(shí)候,img 標(biāo)簽一加載,這個(gè) CSRF 攻擊就會(huì)起作用,在你不知情的情況下向這個(gè)網(wǎng)站付款了。
由于傳統(tǒng)的 Cookie-Session 認(rèn)證存在諸多問(wèn)題,那可以把上面的方案改造一下。
1、改造 Cookie 既然 Cookie 不能在 APP 等非瀏覽器中使用,那就不用 cookie 做客戶端存儲(chǔ),改用其他方式。
改成什么呢?
web 中可以使用 local storage,APP 中使用客戶端數(shù)據(jù)庫(kù),這樣既能這樣就實(shí)現(xiàn)了跨域,并且避免了 CSRF 。
2、服務(wù)端也不存 Session 了,把 Session 信息拿出來(lái)存到 Redis 等內(nèi)存數(shù)據(jù)庫(kù)中,這樣即提高了速度,又避免了 Session 同步問(wèn)題;
經(jīng)過(guò)改造之后變成了如下的認(rèn)證過(guò)程:
下面兩張圖分別演示了首次登錄和非首次登錄的過(guò)程。
經(jīng)過(guò)一頓猛如虎的改造,解決了傳統(tǒng) Cookie-Session 方式存在的問(wèn)題。這種改造需要開發(fā)者在項(xiàng)目中自行完成。改造起來(lái)肯定是費(fèi)時(shí)費(fèi)力的,而且還有可能存在漏洞。
這時(shí),JWT 就可以上場(chǎng)了,JWT 就是一種Cookie-Session改造版的具體實(shí)現(xiàn),讓你省去自己造輪子的時(shí)間,JWT 還有個(gè)好處,那就是你可以不用在服務(wù)端存儲(chǔ)認(rèn)證信息(比如 token),完全由客戶端提供,服務(wù)端只要根據(jù) JWT 自身提供的解密算法就可以驗(yàn)證用戶合法性,而且這個(gè)過(guò)程是安全的。
如果你是剛接觸 JWT,最有疑問(wèn)的一點(diǎn)可能就是: JWT 為什么可以完全依靠客戶端(比如瀏覽器端)就能實(shí)現(xiàn)認(rèn)證功能,認(rèn)證信息全都存在客戶端,怎么保證安全性?
JWT 最后的形式就是個(gè)字符串,它由頭部、載荷與簽名這三部分組成,中間以「.」分隔。像下面這樣:
頭部以 JSON 格式表示,用于指明令牌類型和加密算法。形式如下,表示使用 JWT 格式,加密算法采用 HS256,這是最常用的算法,除此之外還有很多其他的。
{
"alg": "HS256",
"typ": "JWT"
}
對(duì)應(yīng)上圖的紅色 header 部分,需要 Base64 編碼。
用來(lái)存儲(chǔ)服務(wù)器需要的數(shù)據(jù),比如用戶信息,例如姓名、性別、年齡等,要注意的是重要的機(jī)密信息最好不要放到這里,比如密碼等。
{
"name": "古時(shí)的風(fēng)箏",
"introduce": "英俊瀟灑"
}
另外,JWT 還規(guī)定了 7 個(gè)字段供開發(fā)者選用。
這部分信息也是要用 Base64 編碼的。
簽名有一個(gè)計(jì)算公式。
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
Secret
)
使用HMACSHA256算法計(jì)算得出,這個(gè)方法有兩個(gè)參數(shù),前一個(gè)參數(shù)是 (base64 編碼的頭部 + base64 編碼的載荷)用點(diǎn)號(hào)相連,后一個(gè)參數(shù)是自定義的字符串密鑰,密鑰不要暴露在客戶端,而應(yīng)該服務(wù)器知道。
了解了 JWT 的結(jié)構(gòu)和算法后,那怎么使用呢?假設(shè)我這兒有個(gè)網(wǎng)站。
1、在用戶登錄網(wǎng)站的時(shí)候,需要輸入用戶名、密碼或者短信驗(yàn)證的方式登錄,登錄請(qǐng)求到達(dá)服務(wù)端的時(shí)候,服務(wù)端對(duì)賬號(hào)、密碼進(jìn)行驗(yàn)證,然后計(jì)算出 JWT 字符串,返回給客戶端。
2、客戶端拿到這個(gè) JWT 字符串后,存儲(chǔ)到 cookie 或者 瀏覽器的 LocalStorage 中。
3、再次發(fā)送請(qǐng)求,比如請(qǐng)求用戶設(shè)置頁(yè)面的時(shí)候,在 HTTP 請(qǐng)求頭中加入 JWT 字符串,或者直接放到請(qǐng)求主體中。
4、服務(wù)端拿到這串 JWT 字符串后,使用 base64的頭部和 base64 的載荷部分,通過(guò)HMACSHA256算法計(jì)算簽名部分,比較計(jì)算結(jié)果和傳來(lái)的簽名部分是否一致,如果一致,說(shuō)明此次請(qǐng)求沒有問(wèn)題,如果不一致,說(shuō)明請(qǐng)求過(guò)期或者是非法請(qǐng)求。
保證安全性的關(guān)鍵就是 HMACSHA256 或者與它同類型的加密算法,因?yàn)榧用苓^(guò)程是不可逆的,所以不能根據(jù)傳到前端的 JWT 傳反解到密鑰信息。
另外,不同的頭部和載荷加密之后得到的簽名都是不同的,所以,如果有人改了載荷部分的信息,那最后加密出的結(jié)果肯定就和改之前的不一樣的,所以,最后驗(yàn)證的結(jié)果就是不合法的請(qǐng)求。
假設(shè)載荷部分存儲(chǔ)了權(quán)限級(jí)別相關(guān)的字段,強(qiáng)盜拿到 JWT 串后想要修改為更高權(quán)限的級(jí)別,上面剛說(shuō)了,這種情況下是肯定不會(huì)得逞的,因?yàn)榧用艹鰜?lái)的簽名會(huì)不一樣,服務(wù)器可能很容易的判別出來(lái)。
那如果強(qiáng)盜拿到后不做更改,直接用呢,那就沒有辦法了,為了更大程度上防止被強(qiáng)盜盜取,應(yīng)該使用 HTTPS 協(xié)議而不是 HTTP 協(xié)議,這樣可以有效的防止一些中間劫持攻擊行為。
有同學(xué)就要說(shuō)了,這一點(diǎn)也不安全啊,拿到 JWT 串就可以輕松模擬請(qǐng)求了。確實(shí)是這樣,但是前提是你怎么樣能拿到,除了上面說(shuō)的中間劫持外,還有什么辦法嗎?
除非強(qiáng)盜直接拿了你的電腦,那這樣的話,對(duì)不起,不光 JWT 不安全了,其他任何網(wǎng)站,任何認(rèn)證方式都不安全。
雖然這樣的情況很少,但是在使用 JWT 的時(shí)候仍然要注意合理的設(shè)置過(guò)期時(shí)間,不要太長(zhǎng)。
JWT 有個(gè)問(wèn)題,導(dǎo)致很多開發(fā)團(tuán)隊(duì)放棄使用它,那就是一旦頒發(fā)一個(gè) JWT 令牌,服務(wù)端就沒辦法廢棄掉它,除非等到它自身過(guò)期。有很多應(yīng)用默認(rèn)只允許最新登錄的一個(gè)客戶端正常使用,不允許多端登錄,JWT 就沒辦法做到,因?yàn)轭C發(fā)了新令牌,但是老的令牌在過(guò)期前仍然可用。這種情況下,就需要服務(wù)端增加相應(yīng)的邏輯。
JWT 官網(wǎng)列出了各種語(yǔ)言對(duì)應(yīng)的庫(kù),其中 Java 的如下幾個(gè)。
以 java-jwt為例。
1、引入對(duì)應(yīng)的 Maven 包。
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.3</version>
</dependency>
2、在登錄時(shí),調(diào)用 create 方法得到一個(gè)令牌,并返回給前端。
public static String create(){
try {
Algorithm algorithm=Algorithm.HMAC256("secret");
String token=JWT.create()
.withIssuer("auth0")
.withSubject("subject")
.withClaim("name","古時(shí)的風(fēng)箏")
.withClaim("introduce","英俊瀟灑")
.sign(algorithm);
System.out.println(token);
return token;
} catch (JWTCreationException exception){
//Invalid Signing configuration / Couldn't convert Claims.
throw exception;
}
}
3、登錄成功后,再次發(fā)起請(qǐng)求的時(shí)候?qū)?token 放到 header 或者請(qǐng)求體中,服務(wù)端對(duì) token 進(jìn)行驗(yàn)證。
public static Boolean verify(String token){
try {
Algorithm algorithm=Algorithm.HMAC256("secret");
JWTVerifier verifier=JWT.require(algorithm)
.withIssuer("auth0")
.build(); //Reusable verifier instance
DecodedJWT jwt=verifier.verify(token);
String payload=jwt.getPayload();
String name=jwt.getClaim("name").asString();
String introduce=jwt.getClaim("introduce").asString();
System.out.println(payload);
System.out.println(name);
System.out.println(introduce);
return true;
} catch (JWTVerificationException exception){
//Invalid signature/claims
return false;
}
}
4、用 create 方法生成 token,并用 verify 方法驗(yàn)證一下。
public static void main(String[] args){
String token=create();
Boolean result=verify(token);
System.out.println(result);
}
得到下面的結(jié)果
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJzdWJqZWN0IiwiaW50cm9kdWNlIjoi6Iux5L-K5r2H5rSSIiwiaXNzIjoiYXV0aDAiLCJuYW1lIjoi5Y-k5pe255qE6aOO562dIn0.ooQ1K_XyljjHf34Nv5iJvg1MQgVe6jlphxv4eeFt8pA
eyJzdWIiOiJzdWJqZWN0IiwiaW50cm9kdWNlIjoi6Iux5L-K5r2H5rSSIiwiaXNzIjoiYXV0aDAiLCJuYW1lIjoi5Y-k5pe255qE6aOO562dIn0
古時(shí)的風(fēng)箏
英俊瀟灑
true
使用 create 方法創(chuàng)建的 JWT 串可以通過(guò)驗(yàn)證。
而如果我將 JWT 串中的載荷部分,兩個(gè)點(diǎn)號(hào)中間的部分修改一下,然后再調(diào)用 verify 方法驗(yàn)證,會(huì)出現(xiàn) JWTVerificationException異常,不能通過(guò)驗(yàn)證。
關(guān)面試題如下:
JWT (JSON Web Token) 是目前最流行的跨域認(rèn)證解決方案,是一種基于 Token 的認(rèn)證授權(quán)機(jī)制。從 JWT 的全稱可以看出,JWT 本身也是 Token,一種規(guī)范化之后的 JSON 結(jié)構(gòu)的 Token。
Token 自身包含了身份驗(yàn)證所需要的所有信息,因此,我們的服務(wù)器不需要存儲(chǔ) Session 信息。這顯然增加了系統(tǒng)的可用性和伸縮性,大大減輕了服務(wù)端的壓力。
可以看出,JWT 更符合設(shè)計(jì) RESTful API 時(shí)的「Stateless(無(wú)狀態(tài))」原則 。
并且, 使用 Token 認(rèn)證可以有效避免 CSRF 攻擊,因?yàn)?Token 一般是存在在 localStorage 中,使用 JWT 進(jìn)行身份驗(yàn)證的過(guò)程中是不會(huì)涉及到 Cookie 的。
我在 JWT 優(yōu)缺點(diǎn)分析[1]這篇文章中有詳細(xì)介紹到使用 JWT 做身份認(rèn)證的優(yōu)勢(shì)和劣勢(shì)。
下面是 RFC 7519[2] 對(duì) JWT 做的較為正式的定義。
JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted. ——JSON Web Token (JWT)[3]
JWT 本質(zhì)上就是一組字串,通過(guò)(.)切分成三個(gè)為 Base64 編碼的部分:
JWT 通常是這樣的:xxxxx.yyyyy.zzzzz。
示例:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
你可以在 jwt.io[4] 這個(gè)網(wǎng)站上對(duì)其 JWT 進(jìn)行解碼,解碼之后得到的就是 Header、Payload、Signature 這三部分。
Header 和 Payload 都是 JSON 格式的數(shù)據(jù),Signature 由 Payload、Header 和 Secret(密鑰)通過(guò)特定的計(jì)算公式和加密算法得到。
Header 通常由兩部分組成:
示例:
{
"alg": "HS256",
"typ": "JWT"
}
JSON 形式的 Header 被轉(zhuǎn)換成 Base64 編碼,成為 JWT 的第一部分。
Payload 也是 JSON 格式數(shù)據(jù),其中包含了 Claims(聲明,包含 JWT 的相關(guān)信息)。
Claims 分為三種類型:
下面是一些常見的注冊(cè)聲明:
示例:
{
"uid": "ff1212f5-d8d1-4496-bf41-d2dda73de19a",
"sub": "1234567890",
"name": "John Doe",
"exp": 15323232,
"iat": 1516239022,
"scope": ["admin", "user"]
}
Payload 部分默認(rèn)是不加密的,一定不要將隱私信息存放在 Payload 當(dāng)中!!!
JSON 形式的 Payload 被轉(zhuǎn)換成 Base64 編碼,成為 JWT 的第二部分。
Signature 部分是對(duì)前兩部分的簽名,作用是防止 Token(主要是 payload) 被篡改。
這個(gè)簽名的生成需要用到:
簽名的計(jì)算公式如下:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
算出簽名以后,把 Header、Payload、Signature 三個(gè)部分拼成一個(gè)字符串,每個(gè)部分之間用"點(diǎn)"(.)分隔,成為 JWT 的第三部分。
在基于 Token 進(jìn)行身份驗(yàn)證的的應(yīng)用程序中,服務(wù)器通過(guò) Payload、Header 和Secret(密鑰)創(chuàng)建Token(令牌)并將 Token 發(fā)送給客戶端。客戶端接收到 Token 之后,會(huì)將其保存在 Cookie 或者 localStorage 里面,以后客戶端發(fā)出的所有請(qǐng)求都會(huì)攜帶這個(gè)令牌。
簡(jiǎn)化后的步驟如下:
兩點(diǎn)建議:
spring-security-jwt-guide[6] 就是一個(gè)基于 JWT 來(lái)做身份認(rèn)證的簡(jiǎn)單案例,感興趣的可以看看。
有了簽名之后,即使 Token 被泄露或者解惑,黑客也沒辦法同時(shí)篡改 Signature 、Header 、Payload。
這是為什么呢?因?yàn)榉?wù)端拿到 Token 之后,會(huì)解析出其中包含的 Header、Payload 以及 Signature 。服務(wù)端會(huì)根據(jù) Header、Payload、密鑰再次生成一個(gè) Signature。拿新生成的 Signature 和 Token 中的 Signature 作對(duì)比,如果一樣就說(shuō)明 Header 和 Payload 沒有被修改。
不過(guò),如果服務(wù)端的秘鑰也被泄露的話,黑客就可以同時(shí)篡改 Signature 、Header 、Payload 了。黑客直接修改了 Header 和 Payload 之后,再重新生成一個(gè) Signature 就可以了。
密鑰一定保管好,一定不要泄露出去。JWT 安全的核心在于簽名,簽名安全的核心在密鑰。
[1]
JWT 優(yōu)缺點(diǎn)分析: ./advantages&disadvantages-of-jwt.md
[2]
RFC 7519: https://tools.ietf.org/html/rfc7519
[3]
JSON Web Token (JWT): https://tools.ietf.org/html/rfc7519
[4]
jwt.io: https://jwt.io/
[5]
IANA JSON Web Token Registry: https://www.iana.org/assignments/jwt/jwt.xhtml
[6]
spring-security-jwt-guide: https://github.com/Snailclimb/spring-security-jwt-guide
本文內(nèi)容來(lái)源于官方網(wǎng)站,讓我們來(lái)了解下JWT
https://jwt.io/
JWT是一個(gè)開放標(biāo)準(zhǔn)(RFC 7519),完整的名稱是JSON Web Token,以下都簡(jiǎn)稱JWT,它是一種緊湊且獨(dú)立的以JSON對(duì)象的形式在各種場(chǎng)景下安全地傳輸信息。因?yàn)樗菙?shù)字簽名的,可以對(duì)它進(jìn)行驗(yàn)證。可以使用一個(gè)秘密對(duì)JWT進(jìn)行簽名(使用HMAC算法)或使用RSA或ECDSA。
以下是一些適合使用JWT的場(chǎng)景:
認(rèn)證授權(quán)是使用JWT最常見的場(chǎng)景。一旦用戶登錄,每個(gè)后續(xù)請(qǐng)求都將包括JWT,允許用戶訪問(wèn)該令牌允許的路由、服務(wù)和資源。單點(diǎn)登錄是當(dāng)今廣泛使用的一種特性,因?yàn)樗_銷小,而且能夠很容易在不同的域下使用,也就是我們常說(shuō)的跨域。
JWT是在各場(chǎng)景之間安全地傳輸信息的一種好方法。因?yàn)镴WT可以進(jìn)行簽名,例如,使用公鑰/私鑰對(duì),你可以根據(jù)公鑰/私鑰對(duì)來(lái)判斷請(qǐng)求信息是否有效。此外,由于簽名是使用報(bào)頭和負(fù)載計(jì)算的,你還可以驗(yàn)證內(nèi)容有沒有被篡改。
JWT以其緊湊的形式由點(diǎn)分隔的三個(gè)部分組成(.),它們是:
因此,JWT通常是下面這樣的形勢(shì)
Header.Payload.Signature
我們針對(duì)不同的部分別來(lái)介紹:
標(biāo)頭(Header):
標(biāo)頭典型由兩個(gè)部分組成:令牌的類型(即JWT)正在使用的簽名算法(如HMAC SHA 256或RSA)。
例如:
{ "alg": "HS256", "typ": "JWT" }
負(fù)載(Payload)
令牌的第二部分是負(fù)載,它包含了以下部分:
除了官方提供的字段之外,你還可以自定義字段:
{ "sub": "1234567890", "name": "John Doe", "admin": true }
注意:對(duì)于簽名的令牌,這些信息雖然受到保護(hù),但任何人都可以閱讀。除非加密,否則不要將秘密信息放入JWT的有效負(fù)載或頭元素中,如登錄密碼等。
簽名
要?jiǎng)?chuàng)建簽名部分,你必須接受編碼的頭部、編碼的負(fù)載、表頭中的加密算法,并對(duì)其進(jìn)行簽名。
例如,如果要使用HMAC SHA 256算法,則將以下列方式創(chuàng)建簽名:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
簽名用于驗(yàn)證消息在過(guò)程中沒有被更改,對(duì)于用私鑰簽名的令牌,它還可以驗(yàn)證JWT的發(fā)送方是否是它所稱的發(fā)送方。
Base64Url
生成的結(jié)果是三個(gè)Base64-URL字符串,由點(diǎn)分隔,可以在HTML和HTTP環(huán)境中輕松地傳遞,同時(shí)與基于XML的標(biāo)準(zhǔn)(如SAML)相比更加緊湊。
在身份驗(yàn)證中,當(dāng)用戶成功地使用他們的憑據(jù)登錄時(shí),將返回一個(gè)JWT。由于令牌是憑據(jù),因此必須非常小心地防止安全問(wèn)題。通常,你不應(yīng)將令牌保存的時(shí)間超過(guò)所需時(shí)間。
每當(dāng)用戶想訪問(wèn)受保護(hù)的路由或資源時(shí),用戶代理應(yīng)該發(fā)送JWT,通常在請(qǐng)求頭帶上如下:
Authorization: Bearer <token>
在某些情況下,這可能是一種無(wú)狀態(tài)授權(quán)機(jī)制。服務(wù)器的受保護(hù)路由將在授權(quán)標(biāo)頭,如果它存在,則允許用戶訪問(wèn)受保護(hù)的資源。如果JWT包含必要的數(shù)據(jù),那么查詢數(shù)據(jù)庫(kù)中某些操作的需求可能會(huì)減少,盡管情況可能并不總是這樣。
下圖顯示了如何獲取JWT并用于訪問(wèn)API或資源:
請(qǐng)注意,使用簽名的令牌,令牌中包含的所有信息都將公開給用戶或其他各方,即使他們無(wú)法更改它。這意味著不應(yīng)該將秘密信息放入令牌中。
JWT在當(dāng)前的Web或HTTP應(yīng)用開發(fā)中非常受用,本文通過(guò)介紹JWT能讓我們更容易的理解什么是JWT,以及如何使用,并且JWT的工作原理,JWT針對(duì)各個(gè)平臺(tái)都有對(duì)應(yīng)的多個(gè)可選框架使用,因此在理解了JWT的結(jié)構(gòu)和原理之后,我們可以更加簡(jiǎn)單的使用它,如果本文對(duì)你有幫助,請(qǐng)麻煩幫忙轉(zhuǎn)發(fā)、點(diǎn)贊加關(guān)注哦!謝謝!
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。