成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

講真,別再使用JWT了

開發(fā) 開發(fā)工具
在Web應(yīng)用中,使用JWT替代session并不是個(gè)好主意。我并不否認(rèn)JWT的價(jià)值,只是它經(jīng)常被誤用。

摘要:

  • 在Web應(yīng)用中,使用JWT替代session并不是個(gè)好主意。
  • 適合JWT的使用場景。

(圖片來自:https://jwt.io/)

抱歉,當(dāng)了回標(biāo)題黨。我并不否認(rèn)JWT的價(jià)值,只是它經(jīng)常被誤用。

什么是JWT

根據(jù)維基百科的定義,JSON WEB Token(JWT, 讀作 [/dʒɒt/]),是一種基于JSON的、用于在網(wǎng)絡(luò)上聲明某種主張的令牌(token)。JWT通常由三部分組成:頭信息(header),消息體(payload)和簽名(signature)。

頭信息指定了該JWT使用的簽名算法:

  1. header = '{"alg":"HS256","typ":"JWT"}' 

HS256表示使用了HMAC-SHA256來生成簽名。

消息體包含了JWT的意圖:

  1. payload = '{"loggedInAs":"admin","iat":1422779638}'//iat表示令牌生成的時(shí)間 

未簽名的令牌由base64url編碼的頭信息和消息體拼接而成(使用"."分隔),簽名則通過私有的key計(jì)算而成:

  1. key = 'secretkey'   
  2. unsignedToken = encodeBase64(header) + '.' + encodeBase64(payload)   
  3. signature = HMAC-SHA256(key, unsignedToken)  

最后在未簽名的令牌尾部拼接上base64url編碼的簽名(同樣使用"."分隔)就是JWT了:

  1. token = encodeBase64(header) + '.' + encodeBase64(payload) + '.' + encodeBase64(signature)  
  2.  
  3. # token看起來像這樣: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dnZWRJbkFzIjoiYWRtaW4iLCJpYXQiOjE0MjI3Nzk2Mzh9.gzSraSYS8EXBxLN_oWnFSRgCzcmJmMjLiuyu5CSpyHI  

JWT常常被用作保護(hù)服務(wù)端的資源(resource),客戶端通常將JWT通過HTTP的Authorization header發(fā)送給服務(wù)端,服務(wù)端使用自己保存的key計(jì)算、驗(yàn)證簽名以判斷該JWT是否可信:

  1. Authorization: Bearer eyJhbGci*...<snip>...*yu5CSpyHI 

那怎么就誤用了呢

近年來RESTful API開始風(fēng)靡,使用HTTP header來傳遞認(rèn)證令牌似乎變得理所應(yīng)當(dāng),而單頁應(yīng)用(SPA)、前后端分離架構(gòu)似乎正在促成越來越多的WEB應(yīng)用放棄歷史悠久的cookie-session認(rèn)證機(jī)制,轉(zhuǎn)而使用JWT來管理用戶session。支持該方案的人認(rèn)為:

1.該方案更易于水平擴(kuò)展

在cookie-session方案中,cookie內(nèi)僅包含一個(gè)session標(biāo)識(shí)符,而諸如用戶信息、授權(quán)列表等都保存在服務(wù)端的session中。如果把session中的認(rèn)證信息都保存在JWT中,在服務(wù)端就沒有session存在的必要了。當(dāng)服務(wù)端水平擴(kuò)展的時(shí)候,就不用處理session復(fù)制(session replication)/ session黏連(sticky session)或是引入外部session存儲(chǔ)了。

從這個(gè)角度來說,這個(gè)優(yōu)點(diǎn)確實(shí)存在,但實(shí)際上外部session存儲(chǔ)方案已經(jīng)非常成熟了(比如Redis),在一些Framework的幫助下(比如spring-session和hazelcast),session復(fù)制也并沒有想象中的麻煩。所以除非你的應(yīng)用訪問量非常非常非常(此處省略N個(gè)非常)大,使用cookie-session配合外部session存儲(chǔ)完全夠用了。

2. 該方案可防護(hù)CSRF攻擊

跨站請(qǐng)求偽造Cross-site request forgery(簡稱CSRF, 讀作 [sea-surf])是一種典型的利用cookie-session漏洞的攻擊,這里借用spring-security的一個(gè)例子來解釋CSRF:

假設(shè)你經(jīng)常使用bank.example.com進(jìn)行網(wǎng)上轉(zhuǎn)賬,在你提交轉(zhuǎn)賬請(qǐng)求時(shí)bank.example.com的前端代碼會(huì)提交一個(gè)HTTP請(qǐng)求:

  1. POST /transfer HTTP/1.1 
  2. Host: bank.example.com 
  3. cookie: JsessionID=randomidDomain=bank.example.com; Secure; HttpOnly 
  4. Content-Type: application/x-www-form-urlencoded 
  5.  
  6. amount=100.00&routingNumber=1234&account=9876 

你圖方便沒有登出bank.example.com,隨后又訪問了一個(gè)惡意網(wǎng)站,該網(wǎng)站的HTML頁面包含了這樣一個(gè)表單:

  1. <form action="https://bank.example.com/transfer" method="post"> 
  2.   <input type="hidden" name="amount" value="100.00"/> 
  3.   <input type="hidden" name="routingNumber" value="evilsRoutingNumber"/> 
  4.   <input type="hidden" name="account" value="evilsAccountNumber"/> 
  5.   <input type="submit" value="點(diǎn)擊就送!"/> 
  6. </form> 

 

你被“點(diǎn)擊就送”吸引了,當(dāng)你點(diǎn)了提交按鈕時(shí)你已經(jīng)向攻擊者的賬號(hào)轉(zhuǎn)了100元。現(xiàn)實(shí)中的攻擊可能更隱蔽,惡意網(wǎng)站的頁面可能使用Javascript自動(dòng)完成提交。盡管惡意網(wǎng)站沒有辦法盜取你的session cookie(從而假冒你的身份),但惡意網(wǎng)站向bank.example.com發(fā)起請(qǐng)求時(shí),你的cookie會(huì)被自動(dòng)發(fā)送過去。

因此,有些人認(rèn)為前端代碼將JWT通過HTTP header發(fā)送給服務(wù)端(而不是通過cookie自動(dòng)發(fā)送)可以有效防護(hù)CSRF。在這種方案中,服務(wù)端代碼在完成認(rèn)證后,會(huì)在HTTP response的header中返回JWT,前端代碼將該JWT存放到Local Storage里待用,或是服務(wù)端直接在cookie中保存HttpOnly=false的JWT。

[[200145]]

在向服務(wù)端發(fā)起請(qǐng)求時(shí),用Javascript取出JWT(否則前端Javascript代碼無權(quán)從cookie中獲取數(shù)據(jù)),再通過header發(fā)送回服務(wù)端通過認(rèn)證。由于惡意網(wǎng)站的代碼無法獲取bank.example.com的cookie/Local Storage中的JWT,這種方式確實(shí)能防護(hù)CSRF,但將JWT保存在cookie/Local Storage中可能會(huì)給另一種攻擊可乘之機(jī),我們一會(huì)詳細(xì)討論它:跨站腳本攻擊——XSS。

3. 該方案更安全

由于JWT要求有一個(gè)秘鑰,還有一個(gè)算法,生成的令牌看上去不可讀,不少人誤認(rèn)為該令牌是被加密的。但實(shí)際上秘鑰和算法是用來生成簽名的,令牌本身不可讀僅是因?yàn)閎ase64url編碼,可以直接解碼,所以如果JWT中如果保存了敏感的信息,相對(duì)cookie-session將數(shù)據(jù)放在服務(wù)端來說,更不安全。

除了以上這些誤解外,使用JWT管理session還有如下缺點(diǎn):

  • 更多的空間占用。如果將原存在服務(wù)端session中的各類信息都放在JWT中保存在客戶端,可能造成JWT占用的空間變大,需要考慮cookie的空間限制等因素,如果放在Local Storage,則可能受到XSS攻擊。
  • 更不安全。這里是特指將JWT保存在Local Storage中,然后使用Javascript取出后作為HTTP header發(fā)送給服務(wù)端的方案。在Local Storage中保存敏感信息并不安全,容易受到跨站腳本攻擊,跨站腳本(Cross site script,簡稱xss)是一種“HTML注入”,由于攻擊的腳本多數(shù)時(shí)候是跨域的,所以稱之為“跨域腳本”,這些腳本代碼可以盜取cookie或是Local Storage中的數(shù)據(jù)。可以從這篇文章查看XSS攻擊的原理解釋。
  • 無法作廢已頒布的令牌。所有的認(rèn)證信息都在JWT中,由于在服務(wù)端沒有狀態(tài),即使你知道了某個(gè)JWT被盜取了,你也沒有辦法將其作廢。在JWT過期之前(你絕對(duì)應(yīng)該設(shè)置過期時(shí)間),你無能為力。
  • 不易應(yīng)對(duì)數(shù)據(jù)過期。與上一條類似,JWT有點(diǎn)類似緩存,由于無法作廢已頒布的令牌,在其過期前,你只能忍受“過期”的數(shù)據(jù)。

看到這里后,你可能發(fā)現(xiàn),將JWT保存在Local Storage中,并使用JWT來管理session并不是一個(gè)好主意,那有沒有可能“正確”地使用JWT來管理session呢?比如:

  • 不再使用Local Storage存儲(chǔ)JWT,使用cookie,并且設(shè)置HttpOnly=true,這意味著只能由服務(wù)端保存以及通過自動(dòng)回傳的cookie取得JWT,以便防御XSS攻擊。
  • 在JWT的內(nèi)容中加入一個(gè)隨機(jī)值作為CSRF令牌,由服務(wù)端將該CSRF令牌也保存在cookie中,但設(shè)置HttpOnly=false,這樣前端Javascript代碼就可以取得該CSRF令牌,并在請(qǐng)求API時(shí)作為HTTP header傳回。服務(wù)端在認(rèn)證時(shí),從JWT中取出CSRF令牌與header中獲得CSRF令牌比較,從而實(shí)現(xiàn)對(duì)CSRF攻擊的防護(hù)。
  • 考慮到cookie的空間限制(大約4k左右),在JWT中盡可能只放“夠用”的認(rèn)證信息,其他信息放在數(shù)據(jù)庫,需要時(shí)再獲取,同時(shí)也解決之前提到的數(shù)據(jù)過期問題。

這個(gè)方案看上去是挺不錯(cuò)的,恭喜你,你重新發(fā)明了cookie-session,可能實(shí)現(xiàn)還不一定有現(xiàn)有的好。

[[200146]]

那究竟JWT可以用來做什么

我的同事做過一個(gè)形象的解釋:

JWT(其實(shí)還有SAML)最適合的應(yīng)用場景就是“開票”,或者“簽字”。

在有紙化辦公時(shí)代,多部門、多組織之間的協(xié)同工作往往會(huì)需要拿著A部門領(lǐng)導(dǎo)的“簽字”或者“蓋章”去B部門“使用”或者“訪問”對(duì)應(yīng)的資源,其實(shí)這種“領(lǐng)導(dǎo)簽字/蓋章”就是JWT,都是一種由具有一定權(quán)力的實(shí)體“簽發(fā)”并“授權(quán)”的“票據(jù)”。

一般的,這種票據(jù)具有可驗(yàn)證性(領(lǐng)導(dǎo)簽名/蓋章可以被驗(yàn)證,且難于模仿),不可篡改性(涂改過的文件不被接受,除非在涂改處再次簽字確認(rèn));并且這種票據(jù)一般都是“一次性”使用的,在訪問到對(duì)應(yīng)的資源后,該票據(jù)一般會(huì)被資源持有方收回留底,用于后續(xù)的審計(jì)、追溯等用途。

舉兩個(gè)例子:

  • 員工李雷需要請(qǐng)假一天,于是填寫請(qǐng)假申請(qǐng)單,李雷在獲得其主管部門領(lǐng)導(dǎo)簽字后,將請(qǐng)假單交給HR部門韓梅梅,韓梅梅確認(rèn)領(lǐng)導(dǎo)簽字無誤后,將請(qǐng)假單收回,并在公司考勤表中做相應(yīng)記錄。
  • 員工李雷和韓梅梅因工外出需要使用公司汽車一天,于是填寫用車申請(qǐng)單,簽字后李雷將申請(qǐng)單交給車隊(duì)司機(jī)老王,乘坐老王駕駛的車輛外出辦事,同時(shí)老王將用車申請(qǐng)單收回并存檔。

在以上的兩個(gè)例子中,“請(qǐng)假申請(qǐng)單”和“用車申請(qǐng)單”就是JWT中的payload,領(lǐng)導(dǎo)簽字就是base64后的數(shù)字簽名,領(lǐng)導(dǎo)是issuer,“HR部門的韓梅梅”和“司機(jī)老王”即為JWT的audience,audience需要驗(yàn)證領(lǐng)導(dǎo)簽名是否合法,驗(yàn)證合法后根據(jù)payload中請(qǐng)求的資源給予相應(yīng)的權(quán)限,同時(shí)將JWT收回。

放到系統(tǒng)集成的場景中,JWT更適合一次性操作的認(rèn)證:

  • 服務(wù)B你好, 服務(wù)A告訴我,我可以操作

在這里,服務(wù)A負(fù)責(zé)認(rèn)證用戶身份(相當(dāng)于上例中領(lǐng)導(dǎo)批準(zhǔn)請(qǐng)假),并頒布一個(gè)很短過期時(shí)間的JWT給瀏覽器(相當(dāng)于上例中的請(qǐng)假單),瀏覽器(相當(dāng)于上例中的請(qǐng)假員工)在向服務(wù)B的請(qǐng)求中帶上該JWT,則服務(wù)B(相當(dāng)于上例中的HR員工)可以通過驗(yàn)證該JWT來判斷用戶是否有權(quán)執(zhí)行該操作。這樣,服務(wù)B就成為一個(gè)安全的無狀態(tài)的服務(wù)了。

總結(jié)

  • 在Web應(yīng)用中,別再把JWT當(dāng)做session使用,絕大多數(shù)情況下,傳統(tǒng)的cookie-session機(jī)制工作得更好。
  • JWT適合一次性的命令認(rèn)證,頒發(fā)一個(gè)有效期極短的JWT,即使暴露了危險(xiǎn)也很小,由于每次操作都會(huì)生成新的JWT,因此也沒必要保存JWT,真正實(shí)現(xiàn)無狀態(tài)。

【本文是51CTO專欄作者“ThoughtWorks”的原創(chuàng)稿件,微信公眾號(hào):思特沃克,轉(zhuǎn)載請(qǐng)聯(lián)系原作者】

戳這里,看該作者更多好文

責(zé)任編輯:趙寧寧 來源: 51CTO專欄
相關(guān)推薦

2019-07-08 10:00:52

Java內(nèi)存模型并發(fā)

2025-06-19 09:42:22

2022-05-27 21:56:55

索引存儲(chǔ)MySQL 存儲(chǔ)引擎

2023-07-07 09:08:21

2020-12-04 10:05:00

Pythonprint代碼

2020-12-02 11:18:50

print調(diào)試代碼Python

2025-05-19 04:00:00

2025-06-10 02:22:00

2018-09-28 05:25:53

TopK算法代碼

2021-06-09 06:41:11

OFFSETLIMIT分頁

2020-12-11 09:24:19

Elasticsear存儲(chǔ)數(shù)據(jù)

2025-05-30 03:15:00

2019-12-17 09:29:02

數(shù)據(jù)庫架構(gòu)分庫分表

2020-03-24 07:40:00

RabbitMQKafka架構(gòu)師

2024-08-27 09:32:04

2020-06-15 08:12:51

try catch代碼處理器

2023-10-26 16:33:59

float 布局前段CSS

2020-04-22 11:19:07

貪心算法動(dòng)態(tài)規(guī)劃

2024-08-07 10:34:46

2018-11-01 13:49:23

桶排序排序面試
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 精品久久精品 | 国产乱码精品一区二区三区中文 | 国产sm主人调教女m视频 | 毛片视频观看 | 色吧久久| 高清国产午夜精品久久久久久 | 欧产日产国产精品视频 | 一区二区三区高清在线观看 | 欧美国产亚洲一区二区 | 国产传媒视频在线观看 | 一区二区三区欧美 | 亚洲三区在线观看 | 天天干.com| 久久中文一区二区 | 一级大片免费 | 国产一区二区精 | 九九九视频在线观看 | 日韩午夜精品 | 麻豆久久久久久久 | 999精品视频 | 国产精品久久久久久久久久妇女 | 成人蜜桃av | 国产精品美女久久久久aⅴ国产馆 | 伊人久久精品一区二区三区 | 久久亚| 日韩一区二区精品 | 国产一区二区在线播放 | 久久亚洲一区 | 综合成人在线 | 精品久久久一区二区 | 国产蜜臀97一区二区三区 | 国产一区三区在线 | 中文字幕 视频一区 | 99精品免费久久久久久久久日本 | 成人性视频免费网站 | 日本久久网 | 中文字幕一区二区三区精彩视频 | 日本中文字幕日韩精品免费 | 久久三区 | 国产女人精品视频 | 亚洲精品色 |