JWT 設(shè)置token過(guò)期時(shí)間無(wú)效的解決
JWT 設(shè)置token過(guò)期時(shí)間無(wú)效
原因
設(shè)置超時(shí)時(shí)間的順序有誤, 應(yīng)調(diào)用setClaims()方法設(shè)置claims屬性。
在調(diào)用setExpiration()方法設(shè)置超時(shí)時(shí)間。
Date expiresDate = new Date(System.currentTimeMillis() + expire_time);// expire_time為token有效時(shí)長(zhǎng), 單位毫秒
錯(cuò)誤順序示例:
JwtBuilder result = Jwts.builder() ? ? ? ? ? ? ? ? .setExpiration(date) // 超時(shí)時(shí)間設(shè)置在 setClaims之前 ?? ??? ?.setClaims(claims)? ?? ??? ?.signWith(SignatureAlgorithm.HS256, Constants.BASE64SECRET);
正確順序示例:
JwtBuilder result = Jwts.builder() ?? ??? ?.setClaims(claims) // 先調(diào)用setClaims, 在調(diào)用setExpiration ?? ??? ?.setExpiration(date) ?? ??? ?.signWith(SignatureAlgorithm.HS256, Constants.BASE64SECRET);
原因分析
//io.jsonwebtoken.impl.DefaultJwtBuilder#setExpiration 中代碼
@Override
public JwtBuilder setExpiration(Date exp) {
if (exp != null) {
// 設(shè)置的時(shí)間不為空,就調(diào)用ensureClaims方法
ensureClaims().setExpiration(exp);
} else {
if (this.claims != null) {
//noinspection ConstantConditions
this.claims.setExpiration(exp);
}
}
return this;
}
// io.jsonwebtoken.impl.DefaultJwtBuilder#ensureClaims 中代碼
protected Claims ensureClaims() {
// 如果claims為null, 則創(chuàng)建新的示例。 此處沒(méi)有問(wèn)題
if (this.claims == null) {
this.claims = new DefaultClaims();
}
return this.claims;
}
// io.jsonwebtoken.impl.DefaultJwtBuilder#setClaims(io.jsonwebtoken.Claims) 中代碼
@Override
public JwtBuilder setClaims(Claims claims) {
// 直接給claims賦值, 這里個(gè)操作覆蓋了之前設(shè)置的超時(shí)時(shí)間,
// 導(dǎo)致最終構(gòu)造token時(shí), 沒(méi)有設(shè)置超時(shí)時(shí)間
this.claims = claims;
return this;
}JWT token過(guò)期自動(dòng)續(xù)期解決方案
JWT
JWT全稱JSON Web Token,由三部分組成header(頭部,用于描述關(guān)于該JWT的最基本的信息,例如其類(lèi)型以及簽名所用的算法等)、payload(載荷,就是存放有效信息的地方,在這一部分中存放過(guò)期時(shí)間)和signature(簽證,簽證信息)。
token
token就是后端生成的JWT字符串值,在前后端分離中,token是前端訪問(wèn)后端接口的合法身份、權(quán)限的憑證。
token過(guò)期刷新方案
1、單點(diǎn)登錄
用戶登錄,后端驗(yàn)證用戶成功之后生成兩個(gè)token,這兩個(gè)token分別是access_token(訪問(wèn)接口使用的token)、refresh_token(access_token過(guò)期后用于刷續(xù)期的token,注意設(shè)置refresh_token的過(guò)期時(shí)間需比access_token的過(guò)期時(shí)間長(zhǎng)),后端將用戶信息和這兩個(gè)token存放到redis中并返回給前端。
前端在獲取到登錄成功返回的兩個(gè)token之后,將之存放到localStorage本地存儲(chǔ)中。
2、接口請(qǐng)求
前端封裝統(tǒng)一接口請(qǐng)求函數(shù)、token刷新函數(shù),在請(qǐng)求成功之后對(duì)返回結(jié)果進(jìn)行校驗(yàn),如果token過(guò)期,則調(diào)用token刷新函數(shù)請(qǐng)求新的token.
后端在接收到token刷新請(qǐng)求之后通過(guò)結(jié)合redis中存放的用戶信息、token和refresh_token對(duì)請(qǐng)求參數(shù)進(jìn)行驗(yàn)證,驗(yàn)證通過(guò)之后生成新的token和refresh_token存放到redis中并返回給前端。至此完成token刷新。
3、多請(qǐng)求應(yīng)對(duì)
所謂多請(qǐng)求,就是指在短時(shí)間內(nèi)同時(shí)發(fā)生多個(gè)請(qǐng)求,如果此時(shí)token已經(jīng)過(guò)期,那么這些請(qǐng)求都會(huì)出現(xiàn)token過(guò)期請(qǐng)求失敗的情況。
為了避免反復(fù)刷新token,需要設(shè)置一個(gè)刷新token的開(kāi)關(guān)isRefresh,當(dāng)一個(gè)請(qǐng)求出現(xiàn)token過(guò)期的時(shí)候,這個(gè)時(shí)候會(huì)調(diào)用token刷新函數(shù),與此同時(shí)關(guān)閉開(kāi)關(guān)將isRefresh的值設(shè)置為false,避免后續(xù)請(qǐng)求去調(diào)用token刷新函數(shù)。
當(dāng)發(fā)現(xiàn)token過(guò)期時(shí),咱們將請(qǐng)求延緩到token刷新之后再重新執(zhí)行請(qǐng)求,這里采用Promise函數(shù),把每一個(gè)token失效的請(qǐng)求都存到一個(gè)Promise函數(shù)集合里面,當(dāng)token刷新之后打開(kāi)開(kāi)關(guān)將isRefresh的值設(shè)置為true,然后批量執(zhí)行Promise函數(shù)集合里面的Promise函數(shù),返回請(qǐng)求結(jié)果。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring 動(dòng)態(tài)代理實(shí)現(xiàn)代碼實(shí)例
這篇文章主要介紹了Spring 動(dòng)態(tài)代理實(shí)現(xiàn)代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09
Java微服務(wù)開(kāi)發(fā)之Swagger詳解
Swagger 是一個(gè)規(guī)范和完整的框架,用于生成、描述、調(diào)用和可視化 RESTful 風(fēng)格的 Web 服務(wù)??傮w目標(biāo)是使客戶端和文件系統(tǒng)作為服務(wù)器以同樣的速度來(lái)更新。文件的方法,參數(shù)和模型緊密集成到服務(wù)器端的代碼,允許API來(lái)始終保持同步2021-10-10
java啟動(dòng)時(shí)自定義配置文件路徑,自定義log4j2.xml位置方式
這篇文章主要介紹了java啟動(dòng)時(shí)自定義配置文件路徑,自定義log4j2.xml位置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08
在Spring中使用Knife4j進(jìn)行API文檔生成與管理的操作方法
Knife4j 是為Java MVC 框架(如Spring Boot、Spring MVC等)集成 Swagger 生成 API 文檔的增強(qiáng)解決方案,它基于 Swagger 的核心功能,通過(guò)定制化的前端界面和一些額外的特性,本文介紹了在Spring中使用Knife4j進(jìn)行API文檔生成與管理的操作方法,需要的朋友可以參考下2024-12-12
Java圖書(shū)管理系統(tǒng)課程設(shè)計(jì)
這篇文章主要為大家詳細(xì)介紹了Java圖書(shū)管理系統(tǒng)課程設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
JAVA簡(jiǎn)單選擇排序算法原理及實(shí)現(xiàn)
選擇排序(Selection Sort )分為兩種 簡(jiǎn)單選擇排序(Simple Selection Sort) 和樹(shù)形選擇排序2014-01-01
Spring中@Value注解獲取不到配置值問(wèn)題及解決
這篇文章主要介紹了Spring中@Value注解獲取不到配置值問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09

