亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

基于Redis實(shí)現(xiàn)雙加密Token的示例代碼

 更新時(shí)間:2025年01月13日 11:38:39   作者:Asthenia0412  
在現(xiàn)代分布式系統(tǒng)中,Token管理是身份驗(yàn)證和授權(quán)的核心部分,本文將深入分析一個(gè)基于Redis的Token管理實(shí)現(xiàn),探討其設(shè)計(jì)思路、關(guān)鍵代碼邏輯以及實(shí)現(xiàn)細(xì)節(jié),通過(guò)對(duì)源碼的逐層剖析,幫助讀者更好地理解Token管理的實(shí)現(xiàn)原理,需要的朋友可以參考下

1. 核心設(shè)計(jì)思路

TokenStore類的核心設(shè)計(jì)目標(biāo)是實(shí)現(xiàn)一個(gè)高效、安全的Token管理系統(tǒng),主要功能包括:

  • Token的生成與存儲(chǔ):用戶登錄時(shí)生成accessTokenrefreshToken,并將其存儲(chǔ)在Redis中。
  • Token的刷新:通過(guò)refreshToken獲取新的accessToken。
  • Token的刪除:刪除用戶的所有Token,通常用于用戶注銷或管理員禁用用戶。
  • 用戶信息的獲取:通過(guò)accessToken獲取用戶的詳細(xì)信息。

為了實(shí)現(xiàn)這些功能,TokenStore類依賴Redis作為存儲(chǔ)介質(zhì),利用Redis的高性能和豐富的數(shù)據(jù)結(jié)構(gòu)(如String、Set)來(lái)管理Token和用戶信息。

2. 關(guān)鍵代碼邏輯分析

2.1 Token的生成與存儲(chǔ)

在用戶登錄時(shí),系統(tǒng)會(huì)生成一個(gè)accessToken和一個(gè)refreshToken,并將它們存儲(chǔ)在Redis中。以下是storeAccessToken方法的核心邏輯:

public TokenInfoBO storeAccessToken(UserInfoInTokenBO userInfoInToken) {
    TokenInfoBO tokenInfoBO = new TokenInfoBO();
    String accessToken = IdUtil.simpleUUID(); // 生成隨機(jī)的accessToken
    String refreshToken = IdUtil.simpleUUID(); // 生成隨機(jī)的refreshToken

    tokenInfoBO.setUserInfoInToken(userInfoInToken);
    tokenInfoBO.setExpiresIn(getExpiresIn(userInfoInToken.getSysType())); // 設(shè)置Token過(guò)期時(shí)間

    String uidToAccessKeyStr = getUidToAccessKey(getApprovalKey(userInfoInToken)); // 生成uid_to_access的Redis Key
    String accessKeyStr = getAccessKey(accessToken); // 生成access_token的Redis Key
    String refreshToAccessKeyStr = getRefreshToAccessKey(refreshToken); // 生成refresh_to_access的Redis Key

    // 將新的Token加入現(xiàn)有Token列表
    List<String> existsAccessTokens = new ArrayList<>();
    existsAccessTokens.add(accessToken + StrUtil.COLON + refreshToken);

    // 檢查并清理過(guò)期的Token
    Long size = redisTemplate.opsForSet().size(uidToAccessKeyStr);
    if (size != null && size != 0) {
        List<String> tokenInfoBoList = stringRedisTemplate.opsForSet().pop(uidToAccessKeyStr, size);
        if (tokenInfoBoList != null) {
            for (String accessTokenWithRefreshToken : tokenInfoBoList) {
                String[] accessTokenWithRefreshTokenArr = accessTokenWithRefreshToken.split(StrUtil.COLON);
                String accessTokenData = accessTokenWithRefreshTokenArr[0];
                if (BooleanUtil.isTrue(stringRedisTemplate.hasKey(getAccessKey(accessTokenData)))) {
                    existsAccessTokens.add(accessTokenWithRefreshToken);
                }
            }
        }
    }

    // 使用Redis管道批量操作
    redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
        long expiresIn = tokenInfoBO.getExpiresIn();

        byte[] uidKey = uidToAccessKeyStr.getBytes(StandardCharsets.UTF_8);
        byte[] refreshKey = refreshToAccessKeyStr.getBytes(StandardCharsets.UTF_8);
        byte[] accessKey = accessKeyStr.getBytes(StandardCharsets.UTF_8);

        // 將Token列表存入Redis
        for (String existsAccessToken : existsAccessTokens) {
            connection.sAdd(uidKey, existsAccessToken.getBytes(StandardCharsets.UTF_8));
        }

        // 設(shè)置uid_to_access的過(guò)期時(shí)間
        connection.expire(uidKey, expiresIn);

        // 存儲(chǔ)refresh_to_access的映射
        connection.setEx(refreshKey, expiresIn, accessToken.getBytes(StandardCharsets.UTF_8));

        // 存儲(chǔ)access_token對(duì)應(yīng)的用戶信息
        connection.setEx(accessKey, expiresIn, Objects.requireNonNull(redisSerializer.serialize(userInfoInToken)));

        return null;
    });

    // 返回加密后的Token
    tokenInfoBO.setAccessToken(encryptToken(accessToken, userInfoInToken.getSysType()));
    tokenInfoBO.setRefreshToken(encryptToken(refreshToken, userInfoInToken.getSysType()));

    return tokenInfoBO;
}

關(guān)鍵點(diǎn)分析:

  • Token生成:使用IdUtil.simpleUUID()生成隨機(jī)的accessTokenrefreshToken,確保Token的唯一性。
  • Redis數(shù)據(jù)結(jié)構(gòu)
    • uid_to_access:使用Set數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)用戶的所有Token,方便管理和清理。
    • refresh_to_access:使用String數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)refreshTokenaccessToken的映射。
    • access_token:使用String數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)accessToken對(duì)應(yīng)的用戶信息。
  • 過(guò)期時(shí)間管理:根據(jù)用戶類型(sysType)設(shè)置不同的Token過(guò)期時(shí)間,普通用戶和管理員的Token過(guò)期時(shí)間不同。
  • Redis管道操作:通過(guò)executePipelined方法批量執(zhí)行Redis操作,減少網(wǎng)絡(luò)開銷,提升性能。

2.2 Token的刷新

當(dāng)accessToken過(guò)期時(shí),用戶可以通過(guò)refreshToken獲取新的accessToken。以下是refreshToken方法的核心邏輯:

public ServerResponseEntity<TokenInfoBO> refreshToken(String refreshToken) {
    if (StrUtil.isBlank(refreshToken)) {
        return ServerResponseEntity.showFailMsg("refreshToken is blank");
    }
    ServerResponseEntity<String> decryptTokenEntity = decryptToken(refreshToken); // 解密refreshToken
    if (!decryptTokenEntity.isSuccess()) {
        return ServerResponseEntity.transform(decryptTokenEntity);
    }
    String realRefreshToken = decryptTokenEntity.getData();
    String accessToken = stringRedisTemplate.opsForValue().get(getRefreshToAccessKey(realRefreshToken)); // 獲取對(duì)應(yīng)的accessToken

    if (StrUtil.isBlank(accessToken)) {
        return ServerResponseEntity.showFailMsg("refreshToken 已過(guò)期");
    }
    ServerResponseEntity<UserInfoInTokenBO> userInfoByAccessTokenEntity = getUserInfoByAccessToken(accessToken, false);

    if (!userInfoByAccessTokenEntity.isSuccess()) {
        return ServerResponseEntity.showFailMsg("refreshToken 已過(guò)期");
    }

    UserInfoInTokenBO userInfoInTokenBO = userInfoByAccessTokenEntity.getData();
    // 刪除舊的refresh_token和access_token
    stringRedisTemplate.delete(getRefreshToAccessKey(realRefreshToken));
    stringRedisTemplate.delete(getAccessKey(accessToken));
    // 生成新的Token
    TokenInfoBO tokenInfoBO = storeAccessToken(userInfoInTokenBO);

    return ServerResponseEntity.success(tokenInfoBO);
}

關(guān)鍵點(diǎn)分析:

  • Token解密:通過(guò)decryptToken方法解密refreshToken,確保Token的安全性。
  • Token映射:通過(guò)refresh_to_access的映射關(guān)系,找到對(duì)應(yīng)的accessToken。
  • Token清理:刪除舊的refreshTokenaccessToken,防止Token被重復(fù)使用。
  • 新Token生成:調(diào)用storeAccessToken方法生成新的Token。

2.3 Token的刪除

在某些情況下(如用戶注銷或管理員禁用用戶),需要?jiǎng)h除用戶的所有Token。以下是deleteAllToken方法的核心邏輯:

public void deleteAllToken(String appId, Long uid) {
    String uidKey = getUidToAccessKey(getApprovalKey(appId, uid)); // 生成uid_to_access的Redis Key
    Long size = redisTemplate.opsForSet().size(uidKey);
    if (size == null || size == 0) {
        return;
    }
    List<String> tokenInfoBoList = stringRedisTemplate.opsForSet().pop(uidKey, size);

    if (CollUtil.isEmpty(tokenInfoBoList)) {
        return;
    }

    // 遍歷并刪除所有Token
    for (String accessTokenWithRefreshToken : tokenInfoBoList) {
        String[] accessTokenWithRefreshTokenArr = accessTokenWithRefreshToken.split(StrUtil.COLON);
        String accessToken = accessTokenWithRefreshTokenArr[0];
        String refreshToken = accessTokenWithRefreshTokenArr[1];
        redisTemplate.delete(getRefreshToAccessKey(refreshToken));
        redisTemplate.delete(getAccessKey(accessToken));
    }
    redisTemplate.delete(uidKey); // 刪除uid_to_access的Key
}

關(guān)鍵點(diǎn)分析:

  • 批量刪除:通過(guò)uid_to_accessSet數(shù)據(jù)結(jié)構(gòu),獲取用戶的所有Token并批量刪除。
  • 清理映射關(guān)系:刪除refresh_to_accessaccess_token的映射關(guān)系,確保Token完全失效。

3. 總結(jié)

通過(guò)對(duì)TokenStore類的深入分析,我們可以看到其設(shè)計(jì)思路清晰,代碼邏輯嚴(yán)謹(jǐn)。通過(guò)Redis的高效存儲(chǔ)和豐富的數(shù)據(jù)結(jié)構(gòu),實(shí)現(xiàn)了Token的生成、刷新、刪除以及用戶信息的獲取。這種設(shè)計(jì)不僅保證了系統(tǒng)的安全性,還提升了系統(tǒng)的性能和可擴(kuò)展性。

希望本文的源碼分析能夠幫助你更好地理解Token管理的實(shí)現(xiàn)原理。

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

相關(guān)文章

  • 詳解如何清理Redis內(nèi)存碎片

    詳解如何清理Redis內(nèi)存碎片

    操作系統(tǒng)的剩余空間總量足夠,但申請(qǐng)一塊N字節(jié)連續(xù)地址的空間時(shí),剩余內(nèi)存空間中沒(méi)有大小為N字節(jié)的連續(xù)空間,那么這些剩余內(nèi)存空間中,小于N字節(jié)的連續(xù)內(nèi)存空間就是內(nèi)存碎片,本文詳細(xì)介紹了如何清理Redis內(nèi)存碎片,需要的朋友可以參考一下
    2023-04-04
  • Redis 存取 JSON 數(shù)據(jù)示例操作

    Redis 存取 JSON 數(shù)據(jù)示例操作

    JSON 是我們常用的數(shù)據(jù)類型,當(dāng)我們需要在Redis中保存json數(shù)據(jù)時(shí)是怎么存放的呢?一般是用String或者Hash,但還是不太方便,無(wú)法靈活的操作json 數(shù)據(jù),下面通過(guò)本文給大家介紹Redis存取JSON 數(shù)據(jù)示例操作,感興趣的的朋友一起看看吧
    2024-02-02
  • Redis+自定義注解+AOP實(shí)現(xiàn)聲明式注解緩存查詢的示例

    Redis+自定義注解+AOP實(shí)現(xiàn)聲明式注解緩存查詢的示例

    實(shí)際項(xiàng)目中,會(huì)遇到很多查詢數(shù)據(jù)的場(chǎng)景,這些數(shù)據(jù)更新頻率也不是很高,一般我們?cè)跇I(yè)務(wù)處理時(shí),會(huì)對(duì)這些數(shù)據(jù)進(jìn)行緩存,本文主要介紹了Redis+自定義注解+AOP實(shí)現(xiàn)聲明式注解緩存查詢的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-04-04
  • 還不懂Redis?看完這個(gè)趣味小故事就明白了!

    還不懂Redis?看完這個(gè)趣味小故事就明白了!

    這篇文章主要用趣味性的方法講解了redis是什么?并且和MYSQL的區(qū)別是什么,有對(duì)redis不太懂的小伙伴可以來(lái)看一下吧
    2020-12-12
  • 分布式鎖三種實(shí)現(xiàn)方式及對(duì)比

    分布式鎖三種實(shí)現(xiàn)方式及對(duì)比

    這篇文章主要介紹了分布式鎖三種實(shí)現(xiàn)方式及對(duì)比,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • Redis禁用命令、危險(xiǎn)命令及規(guī)避方法

    Redis禁用命令、危險(xiǎn)命令及規(guī)避方法

    這篇文章主要介紹了Redis禁用命令、危險(xiǎn)命令及規(guī)避方法,本文介紹了個(gè)非常致命的兩個(gè)命令以及用配置文件禁用這些命令的方法,需要的朋友可以參考下
    2015-06-06
  • 利用Redis如何實(shí)現(xiàn)自動(dòng)補(bǔ)全功能

    利用Redis如何實(shí)現(xiàn)自動(dòng)補(bǔ)全功能

    這篇文章主要給大家介紹了關(guān)于如何利用Redis如何實(shí)現(xiàn)自動(dòng)補(bǔ)全功能的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Redis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • redis源碼分析教程之壓縮鏈表ziplist詳解

    redis源碼分析教程之壓縮鏈表ziplist詳解

    ziplist結(jié)構(gòu)在redis運(yùn)用非常廣泛,是列表、字典等數(shù)據(jù)類型的底層結(jié)構(gòu)之一。ziplist的優(yōu)點(diǎn)在于能夠一定程度地節(jié)約內(nèi)存。下面這篇文章主要給大家介紹了關(guān)于redis源碼分析教程之壓縮鏈表ziplist的相關(guān)資料,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-12-12
  • Redis慢查詢?nèi)罩九c監(jiān)視器問(wèn)題

    Redis慢查詢?nèi)罩九c監(jiān)視器問(wèn)題

    這篇文章主要介紹了Redis慢查詢?nèi)罩九c監(jiān)視器問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • redis客戶端實(shí)現(xiàn)高可用讀寫分離的方式詳解

    redis客戶端實(shí)現(xiàn)高可用讀寫分離的方式詳解

    基于sentienl 獲取和動(dòng)態(tài)感知 master、slaves節(jié)點(diǎn)信息的變化,我們的讀寫分離客戶端就能具備高可用+動(dòng)態(tài)擴(kuò)容感知能力了,接下來(lái)通過(guò)本文給大家分享redis客戶端實(shí)現(xiàn)高可用讀寫分離的方式,感興趣的朋友一起看看吧
    2021-07-07

最新評(píng)論