JWT 設(shè)置token過期時(shí)間無效的解決
JWT 設(shè)置token過期時(shí)間無效
原因
設(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)建新的示例。 此處沒有問題 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í), 沒有設(shè)置超時(shí)時(shí)間 this.claims = claims; return this; }
JWT token過期自動(dòng)續(xù)期解決方案
JWT
JWT全稱JSON Web Token,由三部分組成header(頭部,用于描述關(guān)于該JWT的最基本的信息,例如其類型以及簽名所用的算法等)、payload(載荷,就是存放有效信息的地方,在這一部分中存放過期時(shí)間)和signature(簽證,簽證信息)。
token
token就是后端生成的JWT字符串值,在前后端分離中,token是前端訪問后端接口的合法身份、權(quán)限的憑證。
token過期刷新方案
1、單點(diǎn)登錄
用戶登錄,后端驗(yàn)證用戶成功之后生成兩個(gè)token,這兩個(gè)token分別是access_token(訪問接口使用的token)、refresh_token(access_token過期后用于刷續(xù)期的token,注意設(shè)置refresh_token的過期時(shí)間需比access_token的過期時(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過期,則調(diào)用token刷新函數(shù)請(qǐng)求新的token.
后端在接收到token刷新請(qǐng)求之后通過結(jié)合redis中存放的用戶信息、token和refresh_token對(duì)請(qǐng)求參數(shù)進(jìn)行驗(yàn)證,驗(yàn)證通過之后生成新的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)過期,那么這些請(qǐng)求都會(huì)出現(xiàn)token過期請(qǐng)求失敗的情況。
為了避免反復(fù)刷新token,需要設(shè)置一個(gè)刷新token的開關(guān)isRefresh,當(dāng)一個(gè)請(qǐng)求出現(xiàn)token過期的時(shí)候,這個(gè)時(shí)候會(huì)調(diào)用token刷新函數(shù),與此同時(shí)關(guān)閉開關(guān)將isRefresh的值設(shè)置為false,避免后續(xù)請(qǐng)求去調(diào)用token刷新函數(shù)。
當(dāng)發(fā)現(xiàn)token過期時(shí),咱們將請(qǐng)求延緩到token刷新之后再重新執(zhí)行請(qǐng)求,這里采用Promise函數(shù),把每一個(gè)token失效的請(qǐng)求都存到一個(gè)Promise函數(shù)集合里面,當(dāng)token刷新之后打開開關(guān)將isRefresh的值設(shè)置為true,然后批量執(zhí)行Promise函數(shù)集合里面的Promise函數(shù),返回請(qǐng)求結(jié)果。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java泛型extends及super區(qū)別實(shí)例解析
這篇文章主要介紹了Java泛型extends及super區(qū)別實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08Java 圖文并茂講解主方法中的String[] args參數(shù)作用
很多老鐵不清楚JAVA主方法中main()里面的的參數(shù)是什么意思,以及有什么作用,接下來給大家用最通俗易懂的話來講解,還不清楚的朋友來看看吧2022-04-04mybatisPlus實(shí)現(xiàn)邏輯刪除,自動(dòng)生成創(chuàng)建時(shí)間和更新時(shí)間方式
MyBatisPlus框架中,通過@TableField(fill=FieldFill.INSERT)和@TableField(fill=FieldFill.UPDATE)注解可以實(shí)現(xiàn)在插入和更新時(shí)自動(dòng)填充字段,比如創(chuàng)建時(shí)間和更新時(shí)間,使用@TableLogic注解標(biāo)識(shí)邏輯刪除字段2024-09-09Java數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)折半查找的算法過程解析
這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)折半查找的算法過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03Java聊天室之實(shí)現(xiàn)一個(gè)服務(wù)器與多個(gè)客戶端通信
這篇文章主要為大家詳細(xì)介紹了Java簡(jiǎn)易聊天室之實(shí)現(xiàn)一個(gè)服務(wù)器與多個(gè)客戶端通信,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以了解一下2022-10-10java中Timer定時(shí)器的使用和啟動(dòng)方式
這篇文章主要介紹了java中Timer定時(shí)器的使用和啟動(dòng)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12Java實(shí)現(xiàn)年獸大作戰(zhàn)游戲詳解
春節(jié)要到了,看慣了前端各種小游戲,確實(shí)做得很好,很精致。本文將為大家介紹一款java版本的年獸大作戰(zhàn)游戲,感興趣的小伙伴可以試一試2022-01-01使用jsoup解析html的table中的文本信息實(shí)例
今天小編就為大家分享一篇使用jsoup解析html的table中的文本信息實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-05-05