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

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

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

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

想象這樣一個場景:

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

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

問題根源

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

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

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

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

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

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

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

后端實現(xiàn)細節(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分鐘內刷新


    @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) {
        // 可以保存草稿后跳轉登錄
    }
    return Promise.reject(error);
});

關于 AccessToken 和 RefreshToken 的機制說明

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

標準雙 Token 模式提升了安全性和用戶體驗,避免因 AccessToken 頻繁刷新帶來的資源浪費。

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

場景問題:

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

推薦方案:

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

總結

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

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

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

相關文章

  • Java序列化原理詳解

    Java序列化原理詳解

    這篇文章主要介紹了Java序列化原理詳解,文章圍繞主題展開詳細的內容介紹,具有一定的參考價值,感興趣的小伙伴可以參考一下
    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?的高性能存儲服務的問題

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

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

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

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

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

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

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

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

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

    很多人表示,java將string類型轉為date類型不知道應該怎樣做,本文就來介紹一下java實現(xiàn)String類型和Date類型相互轉換,具有一定的參考價值,感興趣的可以了解一下
    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使用注入方式,為什么使用注入方式,這系列問題實際歸結起來就是一句話,Spring的注入和IoC(本人關于IoC的闡述)反轉控制是一回事
    2021-08-08
  • Java微信公眾平臺之自定義菜單

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

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

最新評論

建宁县| 休宁县| 扎囊县| 千阳县| 阿克| 荣成市| 沈阳市| 化州市| 洞口县| 施秉县| 黄大仙区| 沿河| 闻喜县| 三河市| 左权县| 平遥县| 凉山| 龙川县| 电白县| 固安县| 昆明市| 天柱县| 吉水县| 阿尔山市| 梅州市| 盘锦市| 九江市| 容城县| 清新县| 翁牛特旗| 甘德县| 乐陵市| 怀仁县| 榆林市| 乐清市| 秀山| 郸城县| 建平县| 永州市| 霍城县| 金门县|