欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java實(shí)現(xiàn)token無(wú)感刷新+處理并發(fā)的后端方案

 更新時(shí)間:2024年11月05日 09:22:26   作者:編程就是n踢r  
在Web應(yīng)用中,Token用于身份驗(yàn)證和會(huì)話(huà)管理,但當(dāng)Token過(guò)期時(shí),可能會(huì)導(dǎo)致用戶(hù)在提交表單或進(jìn)行操作時(shí)突然被重定向到登錄頁(yè)面,本文就來(lái)介紹一下java實(shí)現(xiàn)token無(wú)感刷新+處理并發(fā)的后端方案,感興趣的可以了解一下

問(wèn)題描述:

當(dāng)用戶(hù)通過(guò)登陸后進(jìn)入一個(gè)web網(wǎng)站,會(huì)把token保存到localStorage。假設(shè)token過(guò)期時(shí)間30min。

那么當(dāng)用戶(hù)在網(wǎng)站快樂(lè)地玩耍了30min后,這時(shí)進(jìn)行了一次提交表單,它會(huì)被重定向到登陸頁(yè)面。

作為用戶(hù):我表單填了這么久,點(diǎn)擊提交時(shí)讓我重新登陸?我的體驗(yàn)很不好。

jwt的好處和局限

jwt的好處是:服務(wù)器無(wú)需存儲(chǔ)這些登陸的狀態(tài)

而它的局限是:服務(wù)器無(wú)法主動(dòng)地通知用戶(hù)“你的token過(guò)期了,我重新給你一個(gè)”。

如何解決

方案一:雙token

在登陸時(shí)我們會(huì)生成倆個(gè)token

  • token:表示正常情況下登陸憑證
  • refresh-token:表示需要刷新情況下登陸憑證

假設(shè)前者(token)設(shè)置過(guò)期時(shí)間為30min,后者為1天。

流程

  • time=0min,用戶(hù)成功登陸,后端返回倆個(gè)token(token和refresh-token),前端把它倆保存到localStorage
  • time=10min,用戶(hù)進(jìn)行了一次查詢(xún),前端將倆個(gè)token都發(fā)給后端,后端檢驗(yàn)token,有效,返回結(jié)果,用戶(hù)很開(kāi)心!
  • time=35min,用戶(hù)提交了表單,前端還是將倆個(gè)token發(fā)給后端;后端檢驗(yàn)token,過(guò)期;檢驗(yàn)refresh-token,有效,后端認(rèn)為這是要刷新token,生成新的token和refresh-token,成功返回?cái)?shù)據(jù)和雙token。前端把數(shù)據(jù)渲染,把雙token保存。

token正常過(guò)期的情況:

當(dāng)然,token可以正常過(guò)期,如果在檢驗(yàn)時(shí)refresh-token也過(guò)期,那就說(shuō)明正常過(guò)期

假設(shè)time=0min時(shí)用戶(hù)登陸,time=2天時(shí)用戶(hù)提交了表單,那么后端認(rèn)為這是正常過(guò)期,用戶(hù)需要重新登陸。

流程圖如下:

token刷新并發(fā)問(wèn)題

現(xiàn)在很多登陸是可以多端的,當(dāng)多端并發(fā)都去嘗試刷新token時(shí),會(huì)導(dǎo)致token被重復(fù)刷新

方案二:刷新時(shí)用分布式鎖

可以引入redis緩存中間件,使用緩存加速并處理并發(fā)刷新問(wèn)題。

將雙token生成后存入redis。當(dāng)需要刷新token時(shí),采用double-check+獲取關(guān)于refresh-token的分布式鎖來(lái)實(shí)現(xiàn)。

偽代碼如下:

// 驗(yàn)證和刷新Token的方法
    public String validateAndRefreshToken(String userId, String accessToken, String refreshToken) {
        String storedAccessToken = redisTemplate.opsForValue().get(ACCESS_TOKEN_PREFIX + userId);
        String storedRefreshToken = redisTemplate.opsForValue().get(REFRESH_TOKEN_PREFIX + userId);

        // 檢查Access Token是否有效
        if (storedAccessToken != null && storedAccessToken.equals(accessToken)) {
            return accessToken;  // 直接返回原始的Access Token
        }

        // Access Token無(wú)效,檢查Refresh Token
        if (storedRefreshToken != null && storedRefreshToken.equals(refreshToken)) {
            // 使用雙層檢查和分布式鎖控制高并發(fā)刷新
            String lockKey = "refresh_lock:" + userId;
            boolean lockAcquired = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 5, TimeUnit.SECONDS);
            if (lockAcquired) {
                try {
                    // 再次雙層檢查(避免重復(fù)刷新)
                    storedAccessToken = redisTemplate.opsForValue().get(ACCESS_TOKEN_PREFIX + userId);
                    if (storedAccessToken == null) {
                        // 生成新的Access Token
                        String newAccessToken = generateToken();
                        redisTemplate.opsForValue().set(ACCESS_TOKEN_PREFIX + userId, newAccessToken, 15, TimeUnit.MINUTES);
                        return newAccessToken;
                    } else {
                        return storedAccessToken;  // 直接返回已刷新過(guò)的Token
                    }
                } finally {
                    redisTemplate.delete(lockKey);  // 釋放鎖
                }
            } else {
                // 未獲取到鎖,等待其他線程刷新完成,再次獲取已刷新的Access Token
                return redisTemplate.opsForValue().get(ACCESS_TOKEN_PREFIX + userId);
            }
        }

        // 若Refresh Token也無(wú)效,返回null或拋出異常,需重新登錄
        throw new TokenInvalidException("Access and Refresh Token both expired.");
    }

方案三:過(guò)渡時(shí)間(沒(méi)看懂)

dbf7d02af8054b94ad4f32379ffa45f1.webp

到此這篇關(guān)于java實(shí)現(xiàn)token無(wú)感刷新+處理并發(fā)的后端方案的文章就介紹到這了,更多相關(guān)java token無(wú)感刷新和并發(fā)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java遞歸基礎(chǔ)與遞歸的宏觀語(yǔ)意實(shí)例分析

    Java遞歸基礎(chǔ)與遞歸的宏觀語(yǔ)意實(shí)例分析

    這篇文章主要介紹了Java遞歸基礎(chǔ)與遞歸的宏觀語(yǔ)意,結(jié)合實(shí)例形式分析了java遞歸的相關(guān)原理、操作技巧與注意事項(xiàng),需要的朋友可以參考下
    2020-03-03
  • spring IOC中三種依賴(lài)注入方式

    spring IOC中三種依賴(lài)注入方式

    這篇文章主要介紹了spring IOC中三種依賴(lài)注入方式,Spring使用注入方式,為什么使用注入方式,這系列問(wèn)題實(shí)際歸結(jié)起來(lái)就是一句話(huà),Spring的注入和IoC(本人關(guān)于IoC的闡述)反轉(zhuǎn)控制是一回事
    2021-08-08
  • Java.SE數(shù)組的一些常見(jiàn)練習(xí)題

    Java.SE數(shù)組的一些常見(jiàn)練習(xí)題

    數(shù)組可以看成是相同類(lèi)型元素的一個(gè)集合,在內(nèi)存中是一段連續(xù)的空間,這篇文章主要給大家介紹了關(guān)于Java.SE數(shù)組的一些常見(jiàn)練習(xí)題,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-02-02
  • SpringBoot項(xiàng)目配置postgresql數(shù)據(jù)庫(kù)完整步驟(配置多數(shù)據(jù)源)

    SpringBoot項(xiàng)目配置postgresql數(shù)據(jù)庫(kù)完整步驟(配置多數(shù)據(jù)源)

    PostgreSQL是一種特性非常齊全的自由軟件的對(duì)象-關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)(ORDBMS),下面這篇文章主要給大家介紹了關(guān)于SpringBoot項(xiàng)目配置postgresql數(shù)據(jù)庫(kù)(配置多數(shù)據(jù)源)的相關(guān)資料,需要的朋友可以參考下
    2023-05-05
  • Java基礎(chǔ)-Java變量的聲明和作用域

    Java基礎(chǔ)-Java變量的聲明和作用域

    這篇文章主要介紹了Java變量的聲明和作用域,變量其實(shí)就是內(nèi)存中的一個(gè)存儲(chǔ)空間,用來(lái)存儲(chǔ)數(shù)據(jù),具體的相關(guān)內(nèi)容,需要的小伙伴可以參考下面文章內(nèi)容
    2022-01-01
  • MyBatis關(guān)聯(lián)查詢(xún)的實(shí)現(xiàn)

    MyBatis關(guān)聯(lián)查詢(xún)的實(shí)現(xiàn)

    MyBatis可以通過(guò)定義多個(gè)表的關(guān)聯(lián)關(guān)系,實(shí)現(xiàn)多表查詢(xún),本文主要介紹了MyBatis關(guān)聯(lián)查詢(xún)的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-11-11
  • Gradle使用Maven倉(cāng)庫(kù)的方法

    Gradle使用Maven倉(cāng)庫(kù)的方法

    本篇文章主要介紹了Gradle使用Maven倉(cāng)庫(kù)的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-02-02
  • Java創(chuàng)建對(duì)象(顯式創(chuàng)建和隱含創(chuàng)建)

    Java創(chuàng)建對(duì)象(顯式創(chuàng)建和隱含創(chuàng)建)

    本文詳細(xì)介紹對(duì)象的創(chuàng)建,在 Java 語(yǔ)言中創(chuàng)建對(duì)象分顯式創(chuàng)建與隱含創(chuàng)建兩種情況,顯式創(chuàng)建和隱含創(chuàng)建,,需要的朋友可以參考下面文章的具體內(nèi)容
    2021-09-09
  • Spring和Websocket相結(jié)合實(shí)現(xiàn)消息的推送

    Spring和Websocket相結(jié)合實(shí)現(xiàn)消息的推送

    這篇文章主要介紹了Spring和Websocket相結(jié)合實(shí)現(xiàn)消息的推送的相關(guān)資料,本文介紹的非常詳細(xì)具有參考借鑒價(jià)值,感興趣的朋友一起學(xué)習(xí)吧
    2016-02-02
  • SpringBoot中的PropertySource原理詳解

    SpringBoot中的PropertySource原理詳解

    這篇文章主要介紹了SpringBoot中的PropertySource原理詳解,PropertySource?是一個(gè)非常重要的概念,它允許您在應(yīng)用程序中定義屬性,并將這些屬性注入到?Spring?環(huán)境中,需要的朋友可以參考下
    2023-07-07

最新評(píng)論