JWT 設(shè)置token過期時間無效的解決
JWT 設(shè)置token過期時間無效
原因
設(shè)置超時時間的順序有誤, 應(yīng)調(diào)用setClaims()方法設(shè)置claims屬性。
在調(diào)用setExpiration()方法設(shè)置超時時間。
Date expiresDate = new Date(System.currentTimeMillis() + expire_time);// expire_time為token有效時長, 單位毫秒
錯誤順序示例:
JwtBuilder result = Jwts.builder() ? ? ? ? ? ? ? ? .setExpiration(date) // 超時時間設(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è)置的時間不為空,就調(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)建新的示例。 此處沒有問題
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賦值, 這里個操作覆蓋了之前設(shè)置的超時時間,
// 導(dǎo)致最終構(gòu)造token時, 沒有設(shè)置超時時間
this.claims = claims;
return this;
}JWT token過期自動續(xù)期解決方案
JWT
JWT全稱JSON Web Token,由三部分組成header(頭部,用于描述關(guān)于該JWT的最基本的信息,例如其類型以及簽名所用的算法等)、payload(載荷,就是存放有效信息的地方,在這一部分中存放過期時間)和signature(簽證,簽證信息)。
token
token就是后端生成的JWT字符串值,在前后端分離中,token是前端訪問后端接口的合法身份、權(quán)限的憑證。
token過期刷新方案
1、單點(diǎn)登錄
用戶登錄,后端驗(yàn)證用戶成功之后生成兩個token,這兩個token分別是access_token(訪問接口使用的token)、refresh_token(access_token過期后用于刷續(xù)期的token,注意設(shè)置refresh_token的過期時間需比access_token的過期時間長),后端將用戶信息和這兩個token存放到redis中并返回給前端。
前端在獲取到登錄成功返回的兩個token之后,將之存放到localStorage本地存儲中。
2、接口請求
前端封裝統(tǒng)一接口請求函數(shù)、token刷新函數(shù),在請求成功之后對返回結(jié)果進(jìn)行校驗(yàn),如果token過期,則調(diào)用token刷新函數(shù)請求新的token.
后端在接收到token刷新請求之后通過結(jié)合redis中存放的用戶信息、token和refresh_token對請求參數(shù)進(jìn)行驗(yàn)證,驗(yàn)證通過之后生成新的token和refresh_token存放到redis中并返回給前端。至此完成token刷新。
3、多請求應(yīng)對
所謂多請求,就是指在短時間內(nèi)同時發(fā)生多個請求,如果此時token已經(jīng)過期,那么這些請求都會出現(xiàn)token過期請求失敗的情況。
為了避免反復(fù)刷新token,需要設(shè)置一個刷新token的開關(guān)isRefresh,當(dāng)一個請求出現(xiàn)token過期的時候,這個時候會調(diào)用token刷新函數(shù),與此同時關(guān)閉開關(guān)將isRefresh的值設(shè)置為false,避免后續(xù)請求去調(diào)用token刷新函數(shù)。
當(dāng)發(fā)現(xiàn)token過期時,咱們將請求延緩到token刷新之后再重新執(zhí)行請求,這里采用Promise函數(shù),把每一個token失效的請求都存到一個Promise函數(shù)集合里面,當(dāng)token刷新之后打開開關(guān)將isRefresh的值設(shè)置為true,然后批量執(zhí)行Promise函數(shù)集合里面的Promise函數(shù),返回請求結(jié)果。
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring 動態(tài)代理實(shí)現(xiàn)代碼實(shí)例
這篇文章主要介紹了Spring 動態(tài)代理實(shí)現(xiàn)代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-09-09
java啟動時自定義配置文件路徑,自定義log4j2.xml位置方式
這篇文章主要介紹了java啟動時自定義配置文件路徑,自定義log4j2.xml位置方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08
在Spring中使用Knife4j進(jìn)行API文檔生成與管理的操作方法
Knife4j 是為Java MVC 框架(如Spring Boot、Spring MVC等)集成 Swagger 生成 API 文檔的增強(qiáng)解決方案,它基于 Swagger 的核心功能,通過定制化的前端界面和一些額外的特性,本文介紹了在Spring中使用Knife4j進(jìn)行API文檔生成與管理的操作方法,需要的朋友可以參考下2024-12-12

