JWT 身份認(rèn)證優(yōu)缺點(diǎn)分析以及常見(jiàn)問(wèn)題解決方案

之前分享了一個(gè)使用 Spring Security 實(shí)現(xiàn) JWT 身份認(rèn)證的 Demo况褪,文章地址:適合初學(xué)者入門 Spring Security With JWT 的 Demo。 Demo 非常簡(jiǎn)單耙旦,沒(méi)有介紹到 JWT 存在的一些問(wèn)題。所以沃饶,單獨(dú)抽了一篇文章出來(lái)介紹母廷。為了完成這篇文章,我查閱了很多資料和文獻(xiàn)糊肤,我覺(jué)得應(yīng)該對(duì)大家有幫助琴昆。

相關(guān)閱讀:

Token 認(rèn)證的優(yōu)勢(shì)

相比于 Session 認(rèn)證的方式來(lái)說(shuō)业舍,使用 token 進(jìn)行身份認(rèn)證主要有下面三個(gè)優(yōu)勢(shì):

1.無(wú)狀態(tài)

token 自身包含了身份驗(yàn)證所需要的所有信息,使得我們的服務(wù)器不需要存儲(chǔ) Session 信息升酣,這顯然增加了系統(tǒng)的可用性和伸縮性舷暮,大大減輕了服務(wù)端的壓力。但是噩茄,也正是由于 token 的無(wú)狀態(tài)下面,也導(dǎo)致了它最大的缺點(diǎn):當(dāng)后端在token 有效期內(nèi)廢棄一個(gè) token 或者更改它的權(quán)限的話,不會(huì)立即生效绩聘,一般需要等到有效期過(guò)后才可以沥割。另外,當(dāng)用戶 Logout 的話凿菩,token 也還有效机杜。除非,我們?cè)诤蠖嗽黾宇~外的處理邏輯衅谷。

2.有效避免了CSRF 攻擊

CSRF(Cross Site Request Forgery)一般被翻譯為 跨站請(qǐng)求偽造椒拗,屬于網(wǎng)絡(luò)攻擊領(lǐng)域范圍。相比于 SQL 腳本注入、XSS等等安全攻擊方式蚀苛,CSRF 的知名度并沒(méi)有它們高在验。但是,它的確是每個(gè)系統(tǒng)都要考慮的安全隱患,就連技術(shù)帝國(guó) Google 的 Gmail 在早些年也被曝出過(guò)存在 CSRF 漏洞枉阵,這給 Gmail 的用戶造成了很大的損失译红。

那么究竟什么是 跨站請(qǐng)求偽造 呢?說(shuō)簡(jiǎn)單用你的身份去發(fā)送一些對(duì)你不友好的請(qǐng)求兴溜。舉個(gè)簡(jiǎn)單的例子:

小壯登錄了某網(wǎng)上銀行侦厚,他來(lái)到了網(wǎng)上銀行的帖子區(qū),看到一個(gè)帖子下面有一個(gè)鏈接寫著“科學(xué)理財(cái)拙徽,年盈利率過(guò)萬(wàn)”刨沦,小壯好奇的點(diǎn)開(kāi)了這個(gè)鏈接,結(jié)果發(fā)現(xiàn)自己的賬戶少了10000元膘怕。這是這么回事呢想诅?原來(lái)黑客在鏈接中藏了一個(gè)請(qǐng)求,這個(gè)請(qǐng)求直接利用小壯的身份給銀行發(fā)送了一個(gè)轉(zhuǎn)賬請(qǐng)求,也就是通過(guò)你的 Cookie 向銀行發(fā)出請(qǐng)求岛心。

<a src="http://www.mybank.com/Transfer?bankId=11&money=10000">科學(xué)理財(cái)来破,年盈利率過(guò)萬(wàn)</a>

導(dǎo)致這個(gè)問(wèn)題很大的原因就是: Session 認(rèn)證中 Cookie 中的 session_id 是由瀏覽器發(fā)送到服務(wù)端的,借助這個(gè)特性忘古,攻擊者就可以通過(guò)讓用戶誤點(diǎn)攻擊鏈接徘禁,達(dá)到攻擊效果。

那為什么 token 不會(huì)存在這種問(wèn)題呢髓堪?

我是這樣理解的:一般情況下我們使用 JWT 的話送朱,在我們登錄成功獲得 token 之后,一般會(huì)選擇存放在 local storage 中干旁。然后我們?cè)谇岸送ㄟ^(guò)某些方式會(huì)給每個(gè)發(fā)到后端的請(qǐng)求加上這個(gè) token,這樣就不會(huì)出現(xiàn) CSRF 漏洞的問(wèn)題驶沼。因?yàn)椋词褂袀€(gè)你點(diǎn)擊了非法鏈接發(fā)送了請(qǐng)求到服務(wù)端争群,這個(gè)非法請(qǐng)求是不會(huì)攜帶 token 的回怜,所以這個(gè)請(qǐng)求將是非法的。

但是這樣會(huì)存在 XSS 攻擊中被盜的風(fēng)險(xiǎn)换薄,為了避免 XSS 攻擊玉雾,你可以選擇將 token 存儲(chǔ)在標(biāo)記為httpOnly 的cookie 中。但是专控,這樣又導(dǎo)致了你必須自己提供CSRF保護(hù)抹凳。

具體采用上面哪兩種方式存儲(chǔ) token 呢遏餐,大部分情況下存放在 local storage 下都是最好的選擇伦腐,某些情況下可能需要存放在標(biāo)記為httpOnly 的cookie 中會(huì)更好。

3.適合移動(dòng)端應(yīng)用

使用 Session 進(jìn)行身份認(rèn)證的話失都,需要保存一份信息在服務(wù)器端柏蘑,而且這種方式會(huì)依賴到 Cookie(需要 Cookie 保存 SessionId)幸冻,所以不適合移動(dòng)端。

但是咳焚,使用 token 進(jìn)行身份認(rèn)證就不會(huì)存在這種問(wèn)題洽损,因?yàn)橹灰?token 可以被客戶端存儲(chǔ)就能夠使用,而且 token 還可以跨語(yǔ)言使用革半。

4.單點(diǎn)登錄友好

使用 Session 進(jìn)行身份認(rèn)證的話碑定,實(shí)現(xiàn)單點(diǎn)登錄,需要我們把用戶的 Session 信息保存在一臺(tái)電腦上又官,并且還會(huì)遇到常見(jiàn)的 Cookie 跨域的問(wèn)題延刘。但是,使用 token 進(jìn)行認(rèn)證的話六敬, token 被保存在客戶端碘赖,不會(huì)存在這些問(wèn)題。

Token 認(rèn)證常見(jiàn)問(wèn)題以及解決辦法

1.注銷登錄等場(chǎng)景下 token 還有效

與之類似的具體相關(guān)場(chǎng)景有:

  1. 退出登錄;
  2. 修改密碼;
  3. 服務(wù)端修改了某個(gè)用戶具有的權(quán)限或者角色外构;
  4. 用戶的帳戶被刪除/暫停普泡。
  5. 用戶由管理員注銷;

這個(gè)問(wèn)題不存在于 Session 認(rèn)證方式中审编,因?yàn)樵?Session 認(rèn)證方式中撼班,遇到這種情況的話服務(wù)端刪除對(duì)應(yīng)的 Session 記錄即可。但是割笙,使用 token 認(rèn)證的方式就不好解決了权烧。我們也說(shuō)過(guò)了,token 一旦派發(fā)出去伤溉,如果后端不增加其他邏輯的話般码,它在失效之前都是有效的。那么乱顾,我們?nèi)绾谓鉀Q這個(gè)問(wèn)題呢板祝?查閱了很多資料,總結(jié)了下面幾種方案:

  • 將 token 存入內(nèi)存數(shù)據(jù)庫(kù):將 token 存入 DB 中走净,redis 內(nèi)存數(shù)據(jù)庫(kù)在這里是是不錯(cuò)的選擇券时。如果需要讓某個(gè) token 失效就直接從 redis 中刪除這個(gè) token 即可。但是伏伯,這樣會(huì)導(dǎo)致每次使用 token 發(fā)送請(qǐng)求都要先從 DB 中查詢 token 是否存在的步驟橘洞,而且違背了 JWT 的無(wú)狀態(tài)原則。
  • 黑名單機(jī)制:和上面的方式類似说搅,使用內(nèi)存數(shù)據(jù)庫(kù)比如 redis 維護(hù)一個(gè)黑名單炸枣,如果想讓某個(gè) token 失效的話就直接將這個(gè) token 加入到 黑名單 即可。然后,每次使用 token 進(jìn)行請(qǐng)求的話都會(huì)先判斷這個(gè) token 是否存在于黑名單中适肠。
  • 修改密鑰 (Secret) : 我們?yōu)槊總€(gè)用戶都創(chuàng)建一個(gè)專屬密鑰霍衫,如果我們想讓某個(gè) token 失效,我們直接修改對(duì)應(yīng)用戶的密鑰即可侯养。但是敦跌,這樣相比于前兩種引入內(nèi)存數(shù)據(jù)庫(kù)帶來(lái)了危害更大,比如: ① 如果服務(wù)是分布式的逛揩,則每次發(fā)出新的 token 時(shí)都必須在多臺(tái)機(jī)器同步密鑰柠傍。為此,你需要將必須將機(jī)密存儲(chǔ)在數(shù)據(jù)庫(kù)或其他外部服務(wù)中辩稽,這樣和 Session 認(rèn)證就沒(méi)太大區(qū)別了携兵。② 如果用戶同時(shí)在兩個(gè)瀏覽器打開(kāi)系統(tǒng),或者在手機(jī)端也打開(kāi)了系統(tǒng)搂誉,如果它從一個(gè)地方將賬號(hào)退出徐紧,那么其他地方都要重新進(jìn)行登錄,這是不可取的炭懊。
  • 保持令牌的有效期限短并經(jīng)常輪換 :很簡(jiǎn)單的一種方式并级。但是,會(huì)導(dǎo)致用戶登錄狀態(tài)不會(huì)被持久記錄侮腹,而且需要用戶經(jīng)常登錄嘲碧。

對(duì)于修改密碼后 token 還有效問(wèn)題的解決還是比較容易的,說(shuō)一種我覺(jué)得比較好的方式:使用用戶的密碼的哈希值對(duì) token 進(jìn)行簽名父阻。因此愈涩,如果密碼更改,則任何先前的令牌將自動(dòng)無(wú)法驗(yàn)證加矛。

2.token 的續(xù)簽問(wèn)題

token 有效期一般都建議設(shè)置的不太長(zhǎng)履婉,那么 token 過(guò)期后如何認(rèn)證,如何實(shí)現(xiàn)動(dòng)態(tài)刷新 token斟览,避免用戶經(jīng)常需要重新登錄毁腿?

我們先來(lái)看看在 Session 認(rèn)證中一般的做法:假如 session 的有效期30分鐘,如果 30 分鐘內(nèi)用戶有訪問(wèn)苛茂,就把 session 有效期被延長(zhǎng)30分鐘已烤。

  1. 類似于 Session 認(rèn)證中的做法:這種方案滿足于大部分場(chǎng)景。假設(shè)服務(wù)端給的 token 有效期設(shè)置為30分鐘妓羊,服務(wù)端每次進(jìn)行校驗(yàn)時(shí)胯究,如果發(fā)現(xiàn) token 的有效期馬上快過(guò)期了,服務(wù)端就重新生成 token 給客戶端躁绸≡Q客戶端每次請(qǐng)求都檢查新舊token丙猬,如果不一致,則更新本地的token费韭。這種做法的問(wèn)題是僅僅在快過(guò)期的時(shí)候請(qǐng)求才會(huì)更新 token ,對(duì)客戶端不是很友好。
  2. 每次請(qǐng)求都返回新 token :這種方案的的思路很簡(jiǎn)單庭瑰,但是星持,很明顯,開(kāi)銷會(huì)比較大弹灭。
  3. token 有效期設(shè)置到半夜 :這種方案是一種折衷的方案督暂,保證了大部分用戶白天可以正常登錄,適用于對(duì)安全性要求不高的系統(tǒng)穷吮。
  4. 用戶登錄返回兩個(gè) token :第一個(gè)是 acessToken 逻翁,它的過(guò)期時(shí)間 token 本身的過(guò)期時(shí)間比如半個(gè)小時(shí),另外一個(gè)是 refreshToken 它的過(guò)期時(shí)間更長(zhǎng)一點(diǎn)比如為1天捡鱼“嘶兀客戶端登錄后,將 accessToken和refreshToken 保存在本地驾诈,每次訪問(wèn)將 accessToken 傳給服務(wù)端缠诅。服務(wù)端校驗(yàn) accessToken 的有效性,如果過(guò)期的話乍迄,就將 refreshToken 傳給服務(wù)端管引。如果有效,服務(wù)端就生成新的 accessToken 給客戶端闯两。否則褥伴,客戶端就重新登錄即可。該方案的不足是:① ?需要客戶端來(lái)配合漾狼;② ?用戶注銷的時(shí)候需要同時(shí)保證兩個(gè) token 都無(wú)效重慢;③ 重新請(qǐng)求獲取 token 的過(guò)程中會(huì)有短暫 token 不可用的情況(可以通過(guò)在客戶端設(shè)置定時(shí)器,當(dāng)accessToken 快過(guò)期的時(shí)候逊躁,提前去通過(guò) refreshToken 獲取新的accessToken)伤锚。

總結(jié)

JWT 最適合的場(chǎng)景是不需要服務(wù)端保存用戶狀態(tài)的場(chǎng)景,比如如果考慮到 token 注銷和 token 續(xù)簽的場(chǎng)景話志衣,沒(méi)有特別好的解決方案屯援,大部分解決方案都給 token 加上了狀態(tài),這就有點(diǎn)類似 Session 認(rèn)證了念脯。

Reference

作者:Snailclimb
鏈接:JWT 身份認(rèn)證優(yōu)缺點(diǎn)分析以及常見(jiàn)問(wèn)題解決方案
來(lái)源:github

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末狞洋,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子绿店,更是在濱河造成了極大的恐慌吉懊,老刑警劉巖庐橙,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異借嗽,居然都是意外死亡态鳖,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門恶导,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)浆竭,“玉大人,你說(shuō)我怎么就攤上這事惨寿“钚梗” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵裂垦,是天一觀的道長(zhǎng)顺囊。 經(jīng)常有香客問(wèn)我,道長(zhǎng)蕉拢,這世上最難降的妖魔是什么特碳? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮晕换,結(jié)果婚禮上测萎,老公的妹妹穿的比我還像新娘。我一直安慰自己届巩,他們只是感情好硅瞧,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著恕汇,像睡著了一般腕唧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瘾英,一...
    開(kāi)封第一講書(shū)人閱讀 49,730評(píng)論 1 289
  • 那天枣接,我揣著相機(jī)與錄音,去河邊找鬼缺谴。 笑死但惶,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的湿蛔。 我是一名探鬼主播膀曾,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼阳啥!你這毒婦竟也來(lái)了皮迟?” 一聲冷哼從身側(cè)響起彭谁,我...
    開(kāi)封第一講書(shū)人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤遭贸,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后耳高,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡所踊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年泌枪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秕岛。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡碌燕,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瓣蛀,到底是詐尸還是另有隱情,我是刑警寧澤雷厂,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布惋增,位于F島的核電站,受9級(jí)特大地震影響改鲫,放射性物質(zhì)發(fā)生泄漏诈皿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一像棘、第九天 我趴在偏房一處隱蔽的房頂上張望稽亏。 院中可真熱鬧,春花似錦缕题、人聲如沸截歉。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)瘪松。三九已至,卻和暖如春锨阿,著一層夾襖步出監(jiān)牢的瞬間宵睦,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工墅诡, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留壳嚎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓末早,卻偏偏與公主長(zhǎng)得像烟馅,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子然磷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348