最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot無感刷新Token的實(shí)現(xiàn)示例

 更新時間:2025年07月21日 11:02:36   作者:星辰聊技術(shù)  
無感刷新Token避免會話過期導(dǎo)致數(shù)據(jù)丟失,通過后端動態(tài)續(xù)簽或前端主動請求,結(jié)合雙Token機(jī)制,實(shí)現(xiàn)身份憑證自動更新,感興趣的可以了解一下

背景問題:為什么需要無感刷新?

想象這樣一個場景:

“我正在后臺管理系統(tǒng)中錄入數(shù)據(jù),頁面突然跳轉(zhuǎn)回登錄界面,之前填寫的內(nèi)容全沒了!”

這是典型的 Token 到期導(dǎo)致會話失效 的問題,尤其在使用 Redis 等緩存中間件存儲 Token 時尤為常見。

問題根源

后端通常通過 JWT 來實(shí)現(xiàn)無狀態(tài)身份驗(yàn)證,但 JWT 的缺陷也很明顯:過期即失效,無法修改或撤銷。如果不設(shè)計 Token 刷新機(jī)制,用戶體驗(yàn)將大打折扣。

核心策略:Token 無感續(xù)簽方案概述

方案一:后端自動續(xù)期(推薦)

在每次用戶請求時,后端檢查當(dāng)前 Token 的有效時間:

  • 若臨近過期(如小于5分鐘) ,則動態(tài)生成一個新 Token,加入響應(yīng)頭中返回;
  • 前端攔截響應(yīng)頭,若發(fā)現(xiàn)新的 Token,與本地不一致則自動更新本地 Token。

方案二:前端主動續(xù)簽(補(bǔ)充方案)

  • 前端維護(hù)一對 Token:access_token(短期)+ refresh_token(長期);
  • 每隔一段時間,前端使用 refresh_token 去調(diào)用刷新接口,獲取新的 access_token。

后端實(shí)現(xiàn)細(xì)節(jié)

依賴配置(pom.xml)

<dependencies>
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>5.5.1</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.33</version>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.9.1</version>
    </dependency>
</dependencies>

JWT 工具類JwtUtil.java

 代碼路徑:/src/main/java/com/demo/auth/utils/JwtUtil.java

package com.demo.auth.utils;


import io.jsonwebtoken.*;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.*;


public class JwtUtil {
    public static final long JWT_TTL = 1000L * 60 * 60 * 24; // 24小時
    public static final String JWT_KEY = "qx";


    public static String createJWT(String subject) {
        return getJwtBuilder(subject, null, UUID.randomUUID().toString().replace("-", "")).compact();
    }


    public static String createJWT(String subject, Long ttlMillis) {
        return getJwtBuilder(subject, ttlMillis, UUID.randomUUID().toString()).compact();
    }


    private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) {
        long nowMillis = System.currentTimeMillis();
        long expMillis = (ttlMillis != null ? nowMillis + ttlMillis : nowMillis + JWT_TTL);
        SecretKey secretKey = generalKey();
        return Jwts.builder()
                .setId(uuid)
                .setSubject(subject)
                .setIssuer("icoderoad")
                .setIssuedAt(new Date(nowMillis))
                .setExpiration(new Date(expMillis))
                .signWith(SignatureAlgorithm.HS256, secretKey);
    }


    public static Claims parseJWT(String jwt) throws Exception {
        return Jwts.parser()
                .setSigningKey(generalKey())
                .parseClaimsJws(jwt)
                .getBody();
    }


    public static SecretKey generalKey() {
        byte[] key = Base64.getDecoder().decode(JWT_KEY);
        return new SecretKeySpec(key, 0, key.length, "AES");
    }


    public static Date getExpiration(String jwt) {
        try {
            return parseJWT(jwt).getExpiration();
        } catch (Exception e) {
            throw new RuntimeException("Token 解析失敗", e);
        }
    }
}

Token 攔截與續(xù)簽邏輯

 攔截器路徑:/src/main/java/com/demo/auth/interceptor/AuthInterceptor.java

public class AuthInterceptor implements HandlerInterceptor {


    private static final long REFRESH_THRESHOLD = 1000L * 60 * 5; // 剩余5分鐘內(nèi)刷新


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {


        String token = request.getHeader("Authorization");
        if (StringUtils.isEmpty(token)) {
            throw new RuntimeException("未登錄");
        }


        Claims claims = JwtUtil.parseJWT(token);
        long now = System.currentTimeMillis();
        long exp = claims.getExpiration().getTime();


        if (exp - now < REFRESH_THRESHOLD) {
            String newToken = JwtUtil.createJWT(claims.getSubject());
            response.setHeader("X-Token-Refresh", newToken);
        }


        return true;
    }
}

前端處理邏輯(以 Vue + Axios 為例)

前端攔截代碼:

axios.interceptors.response.use(response => {
    const newToken = response.headers['x-token-refresh'];
    if (newToken && newToken !== localStorage.getItem('access_token')) {
        localStorage.setItem('access_token', newToken);
    }
    return response;
}, error => {
    // 處理401
    if (error.response.status === 401) {
        // 可以保存草稿后跳轉(zhuǎn)登錄
    }
    return Promise.reject(error);
});

關(guān)于 AccessToken 和 RefreshToken 的機(jī)制說明

類型用途特點(diǎn)
AccessToken攜帶用戶身份,頻繁使用安全風(fēng)險高,需短時過期
RefreshToken用于續(xù)簽 AccessToken不暴露給前端,一般保存在 Cookie 或 HttpOnly

標(biāo)準(zhǔn)雙 Token 模式提升了安全性和用戶體驗(yàn),避免因 AccessToken 頻繁刷新帶來的資源浪費(fèi)。

特別討論:表單靜默超時的處理策略

場景問題:

用戶長時間填寫表單,沒有發(fā)出任何請求,點(diǎn)擊提交時發(fā)現(xiàn) token 已失效,被重定向到登錄頁,數(shù)據(jù)全丟。

推薦方案:

  • 提交失敗后前端本地緩存表單數(shù)據(jù);
  • 登錄成功后回顯草稿,確保用戶體驗(yàn)不受損;
  • 或者在用戶輸入行為時定期心跳請求,觸發(fā)后端續(xù)簽。

總結(jié)

實(shí)現(xiàn)無感刷新 Token,是用戶體驗(yàn)與安全性協(xié)同優(yōu)化的重要實(shí)踐。通過后端智能判斷與前端攔截配合,結(jié)合雙 Token 模式或動態(tài)續(xù)簽機(jī)制,我們可以實(shí)現(xiàn):

用戶操作不中斷 身份憑證自動續(xù)期 安全控制粒度更靈活

到此這篇關(guān)于SpringBoot無感刷新Token的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)SpringBoot無感刷新Token內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java序列化原理詳解

    Java序列化原理詳解

    這篇文章主要介紹了Java序列化原理詳解,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,感興趣的小伙伴可以參考一下
    2022-06-06
  • 淺談在Spring中如何使用數(shù)據(jù)源(DBCP、C3P0、JNDI)

    淺談在Spring中如何使用數(shù)據(jù)源(DBCP、C3P0、JNDI)

    這篇文章主要介紹了淺談在Spring中如何使用數(shù)據(jù)源(DBCP、C3P0、JNDI),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-10-10
  • 解析SpringBoot?搭建基于?MinIO?的高性能存儲服務(wù)的問題

    解析SpringBoot?搭建基于?MinIO?的高性能存儲服務(wù)的問題

    Minio是Apache?License?v2.0下發(fā)布的對象存儲服務(wù)器,使用MinIO構(gòu)建用于機(jī)器學(xué)習(xí),分析和應(yīng)用程序數(shù)據(jù)工作負(fù)載的高性能基礎(chǔ)架構(gòu)。這篇文章主要介紹了SpringBoot?搭建基于?MinIO?的高性能存儲服務(wù),需要的朋友可以參考下
    2022-03-03
  • 使用SpringBoot整合Sharding Sphere實(shí)現(xiàn)數(shù)據(jù)脫敏的示例

    使用SpringBoot整合Sharding Sphere實(shí)現(xiàn)數(shù)據(jù)脫敏的示例

    Apache ShardingSphere數(shù)據(jù)脫敏模塊,通過SQL攔截與改寫實(shí)現(xiàn)敏感信息加密存儲,解決手動處理繁瑣及系統(tǒng)改造難題,支持Spring和Spring Boot配置,本文通過實(shí)例代碼介紹如何使用SpringBoot整合Sharding Sphere實(shí)現(xiàn)數(shù)據(jù)脫敏,感興趣的朋友一起看看吧
    2025-06-06
  • Java實(shí)現(xiàn)批量修改txt文件名稱的方法示例

    Java實(shí)現(xiàn)批量修改txt文件名稱的方法示例

    這篇文章主要介紹了Java實(shí)現(xiàn)批量修改txt文件名稱的方法,結(jié)合實(shí)例形式分析了Java針對目錄文件遍歷及文件讀寫、屬性操作等相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2019-03-03
  • Java基礎(chǔ)高級綜合練習(xí)題撲克牌的創(chuàng)建

    Java基礎(chǔ)高級綜合練習(xí)題撲克牌的創(chuàng)建

    今天小編就為大家分享一篇關(guān)于Java基礎(chǔ)高級綜合練習(xí)題撲克牌的創(chuàng)建,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • java實(shí)現(xiàn)String類型和Date類型相互轉(zhuǎn)換

    java實(shí)現(xiàn)String類型和Date類型相互轉(zhuǎn)換

    很多人表示,java將string類型轉(zhuǎn)為date類型不知道應(yīng)該怎樣做,本文就來介紹一下java實(shí)現(xiàn)String類型和Date類型相互轉(zhuǎn)換,具有一定的參考價值,感興趣的可以了解一下
    2023-10-10
  • Java遍歷Json中的key和value問題

    Java遍歷Json中的key和value問題

    這篇文章主要介紹了Java遍歷Json中的key和value問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • spring IOC中三種依賴注入方式

    spring IOC中三種依賴注入方式

    這篇文章主要介紹了spring IOC中三種依賴注入方式,Spring使用注入方式,為什么使用注入方式,這系列問題實(shí)際歸結(jié)起來就是一句話,Spring的注入和IoC(本人關(guān)于IoC的闡述)反轉(zhuǎn)控制是一回事
    2021-08-08
  • Java微信公眾平臺之自定義菜單

    Java微信公眾平臺之自定義菜單

    這篇文章主要為大家詳細(xì)介紹了Java微信公眾平臺之自定義菜單,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-05-05

最新評論

蒙自县| 郴州市| 新田县| 博乐市| 卓尼县| 信宜市| 泉州市| 鄂尔多斯市| 张家界市| 三门峡市| 太谷县| 色达县| 金昌市| 淄博市| 元朗区| 广德县| 从江县| 昌平区| 淄博市| 威海市| 浦北县| 察哈| 睢宁县| 高淳县| 博爱县| 巴塘县| 卢氏县| 托克托县| 陈巴尔虎旗| 丹阳市| 治多县| 青铜峡市| 邯郸县| 句容市| 三亚市| 南岸区| 双牌县| 奎屯市| 中牟县| 苏州市| 汉川市|