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

基于 Redis 的 JWT令牌失效處理方案(實現(xiàn)步驟)

 更新時間:2024年03月05日 10:35:36   作者:Mr.VK  
當(dāng)用戶登錄狀態(tài)到登出狀態(tài)時,對應(yīng)的JWT的令牌需要設(shè)置為失效狀態(tài),這時可以使用基于Redis 的黑名單方案來實現(xiàn)JWT令牌失效,本文給大家分享基于 Redis 的 JWT令牌失效處理方案,感興趣的朋友一起看看吧

應(yīng)用場景

當(dāng)用戶登錄狀態(tài)到登出狀態(tài)時,對應(yīng)的JWT的令牌需要設(shè)置為失效狀態(tài),這時可以使用基于 Redis 的黑名單方案來實現(xiàn)JWT令牌失效。

基于 Redis 的黑名單方案

當(dāng)用戶需要登出系統(tǒng)時,將用戶攜帶的Token進(jìn)行解析,解碼出JWT令牌,取出對應(yīng)的 UUID 過期時間 ,用過期的時間減去當(dāng)前的時間,計算出這個Key的過期時間,再以這兩個字段拼接作為 Key 并設(shè)置好過期時間存儲到 Redis 中,如果有黑客拿竊取出來的JWT令牌進(jìn)行登錄,只要判斷這個JWT令牌是否在黑名單就可以。

實現(xiàn)步驟

1.獲得攜帶的Token解析并取出JWT令牌的代碼

這段代碼實現(xiàn)了對指定 JWT 的驗證和使令牌失效的操作。

  • 首先,通過調(diào)用 convertToken(headerToken) 方法將傳入的頭部令牌 headerToken 轉(zhuǎn)換成實際的 JWT 字符串 token。
  • 然后,使用 HMAC256 算法和預(yù)設(shè)的密鑰 key 創(chuàng)建一個算法實例 algorithm。
  • 接下來,使用算法實例 algorithm 構(gòu)建一個 JWT 驗證器 jwtVerifier。這個驗證器將用于驗證 JWT 的有效性。
  • 在 try-catch 塊中,首先通過調(diào)用 jwtVerifier.verify(token) 方法對 JWT 進(jìn)行驗證。如果驗證成功,則返回一個 DecodedJWT 對象 verify,其中包含了 JWT 的解碼信息,如令牌的唯一標(biāo)識符(ID)和過期時間等。
  • 接著,調(diào)用 deleteToken(verify.getId(), verify.getExpiresAt()) 方法來刪除指定令牌,并將其加入到黑名單中進(jìn)行失效處理。這里使用了 verify 對象中的 ID 和過期時間作為參數(shù)。
  • 最后,如果在驗證 JWT 過程中發(fā)生了 JWTVerificationException 異常,即 JWT 驗證失敗,則捕獲該異常,并返回 false 表示令牌失效操作失敗。
    /**
     * 讓指定Jwt令牌失效
     * @param headerToken 請求頭中攜帶的令牌
     * @return 是否操作成功
     */
    public boolean invalidateJwt(String headerToken){
        String token = this.convertToken(headerToken);
        Algorithm algorithm = Algorithm.HMAC256(key);
        JWTVerifier jwtVerifier = JWT.require(algorithm).build();
        try {
            DecodedJWT verify = jwtVerifier.verify(token);
            return deleteToken(verify.getId(), verify.getExpiresAt());
        } catch (JWTVerificationException e) {
            return false;
        }
    }

2.檢查指定 UUID 的令牌是否為無效的(已加入黑名單)

這段代碼用于檢查指定 UUID 的令牌是否為無效的(已加入黑名單),通過判斷 Redis 數(shù)據(jù)庫中是否存在相應(yīng)的鍵來決定令牌的有效性。如果鍵存在,則表示令牌已失效;如果鍵不存在,則表示令牌仍然有效。

    /**
     * 驗證Token是否被列入Redis黑名單
     * @param uuid 令牌ID
     * @return 是否操作成功
     */
    private boolean isInvalidToken(String uuid){
        return Boolean.TRUE.equals(template.hasKey(Const.JWT_BLACK_LIST + uuid));
    }

3.將Token列入Redis黑名單中

這段代碼實現(xiàn)了對指定令牌的刪除和加入黑名單的操作,用于管理令牌的有效性和安全性。

  • 首先,通過調(diào)用 isInvalidToken(uuid) 方法來檢查指定的 UUID 是否為無效的令牌。如果 isInvalidToken 方法返回 true,則說明該令牌無效,此時直接返回 false,不執(zhí)行后續(xù)操作。
  • 獲取當(dāng)前時間 now,然后計算令牌的過期時間與當(dāng)前時間的差值,并取最大值作為令牌的失效時間 expire。這里使用了 Math.max 方法來確保失效時間不會小于 0。
  • 最后,通過 Redis 的 template 對象調(diào)用 opsForValue().set() 方法,將指定 UUID 的令牌加入到名為 Const.JWT_BLACK_LIST + uuid 的鍵中,并設(shè)置過期時間為 expire 毫秒。這樣就將該令牌加入到了黑名單中,使其在一定時間后失效。
  • 最終,方法返回 true 表示成功刪除令牌并將其加入黑名單。
    /**
     * 將Token列入Redis黑名單中
     * @param uuid 令牌ID
     * @param time 過期時間
     * @return 是否操作成功
     */
    private boolean deleteToken(String uuid, Date time){
        if(this.isInvalidToken(uuid))
            return false;
        Date now = new Date();
        long expire = Math.max(time.getTime() - now.getTime(), 0);
        template.opsForValue().set(Const.JWT_BLACK_LIST + uuid, "", expire, TimeUnit.MILLISECONDS);
        return true;
    }
public final class Const {
    //JWT令牌
    public final static String JWT_BLACK_LIST = "jwt:blacklist:";
    public final static String JWT_FREQUENCY = "jwt:frequency:";
}

對應(yīng)完整的代碼如下:

@Component
public class JwtUtils {
    @Autowired
    private StringRedisTemplate template;
    @Value("${spring.security.jwt.key}")
    String key;
    @Value("${spring.security.jwt.expire}")
    int expire;
    /**
     * 讓指定Jwt令牌失效
     * @param headerToken 請求頭中攜帶的令牌
     * @return 是否操作成功
     */
    public boolean invalidateJwt(String headerToken){
        String token = this.convertToken(headerToken);
        Algorithm algorithm = Algorithm.HMAC256(key);
        JWTVerifier jwtVerifier = JWT.require(algorithm).build();
        try {
            DecodedJWT verify = jwtVerifier.verify(token);
            return deleteToken(verify.getId(), verify.getExpiresAt());
        } catch (JWTVerificationException e) {
            return false;
        }
    }
    /**
     * 將Token列入Redis黑名單中
     * @param uuid 令牌ID
     * @param time 過期時間
     * @return 是否操作成功
     */
    private boolean deleteToken(String uuid, Date time){
        if(this.isInvalidToken(uuid))
            return false;
        Date now = new Date();
        long expire = Math.max(time.getTime() - now.getTime(), 0);
        template.opsForValue().set(Const.JWT_BLACK_LIST + uuid, "", expire, TimeUnit.MILLISECONDS);
        return true;
    }
    /**
     * 驗證Token是否被列入Redis黑名單
     * @param uuid 令牌ID
     * @return 是否操作成功
     */
    private boolean isInvalidToken(String uuid){
        return Boolean.TRUE.equals(template.hasKey(Const.JWT_BLACK_LIST + uuid));
    }
    public DecodedJWT resolveJwt(String headerToken) {
        String token = this.convertToken(headerToken);
        if (token == null) {
            return null;
        }
        Algorithm algorithm = Algorithm.HMAC256(key);
        JWTVerifier jwtVerifier = JWT.require(algorithm).build();
        try {
            DecodedJWT verify = jwtVerifier.verify(token);
            if(this.isInvalidToken(verify.getId())) return null;
            Date expireAt = verify.getExpiresAt();
            return new Date().after(expireAt) ? null : verify;
        } catch (JWTVerificationException e) {
            return null;
        }
    }
    public UserDetails toUser(DecodedJWT jwt) {
        Map<String, Claim> claims = jwt.getClaims();
        return User.withUsername(claims.get("name").asString())
                .password("********")
                .authorities(claims.get("authorities").asArray(String.class))
                .build();
    }
    public Integer toId(DecodedJWT jwt) {
        Map<String, Claim> claims = jwt.getClaims();
        return claims.get("id").asInt();
    }
    public String createJwt(UserDetails details, int id, String username) {
        Algorithm algorithm = Algorithm.HMAC256(key);
        Date expire = this.expireTime();
        return JWT.create()
                .withJWTId(UUID.randomUUID().toString())
                .withClaim("id", id)
                .withClaim("name", username)
                .withClaim("authorities", details.getAuthorities().stream().map(GrantedAuthority::getAuthority).toList())
                .withExpiresAt(expire)
                .withIssuedAt(new Date())
                .sign(algorithm);
    }
    public Date expireTime() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.HOUR, expire * 24);
        return calendar.getTime();
    }
    private String convertToken(String headerToken) {
        if(headerToken == null || !headerToken.startsWith("Bearer ")) {
            return null;
        }
        return headerToken.substring(7);
    }
}

到此這篇關(guān)于基于 Redis 的 JWT令牌失效方案的文章就介紹到這了,更多相關(guān)Redis JWT令牌失效內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Redis中LRU算法和LFU算法的區(qū)別小結(jié)

    Redis中LRU算法和LFU算法的區(qū)別小結(jié)

    在Redis中,LRU算法和LFU算法是兩種常用的緩存淘汰算法,它們可以幫助我們優(yōu)化緩存性能,本文主要介紹了Redis中LRU算法和LFU算法的區(qū)別,感興趣的可以了解一下
    2023-12-12
  • Redis?哈希Hash底層數(shù)據(jù)結(jié)構(gòu)詳解

    Redis?哈希Hash底層數(shù)據(jù)結(jié)構(gòu)詳解

    這篇文章主要介紹了Redis?哈希Hash底層數(shù)據(jù)結(jié)構(gòu)詳解的相關(guān)資料,需要的朋友可以參考下
    2022-08-08
  • 控制Redis的hash的field中的過期時間

    控制Redis的hash的field中的過期時間

    這篇文章主要介紹了控制Redis的hash的field中的過期時間問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • Redis本地/遠(yuǎn)程(外部)連接失敗問題及解決

    Redis本地/遠(yuǎn)程(外部)連接失敗問題及解決

    這篇文章主要介紹了Redis本地/遠(yuǎn)程(外部)連接失敗問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • redis性能優(yōu)化之生產(chǎn)中實際遇到的問題及排查總結(jié)

    redis性能優(yōu)化之生產(chǎn)中實際遇到的問題及排查總結(jié)

    這篇文章主要介紹了redis性能優(yōu)化之生產(chǎn)中實際遇到的問題及排查總結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • Redis之BigKey與HotKey問題詳解

    Redis之BigKey與HotKey問題詳解

    在Redis的實際使用過程中,BigKey和 HotKey是兩個常見且可能導(dǎo)致嚴(yán)重性能問題的問題,它們可能導(dǎo)致 Redis 實例響應(yīng)變慢、內(nèi)存使用不均、甚至服務(wù)不可用,下面就來介紹一下這兩個的問題
    2026-02-02
  • Linux環(huán)境下升級redis的詳細(xì)步驟記錄

    Linux環(huán)境下升級redis的詳細(xì)步驟記錄

    這篇文章主要給大家介紹了關(guān)于Linux環(huán)境下升級redis的詳細(xì)步驟,描述了如何從舊版本升級到新版本Redis,包括備份舊數(shù)據(jù)、下載和安裝新版本、復(fù)制配置文件和數(shù)據(jù)、停止舊版本并啟動新版本的過程,需要的朋友可以參考下
    2024-12-12
  • Redis特殊數(shù)據(jù)類型Geospatial地理空間

    Redis特殊數(shù)據(jù)類型Geospatial地理空間

    這篇文章主要為大家介紹了Redis特殊數(shù)據(jù)類型Geospatial地理空間,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • 一文詳解如何停止/重啟/啟動Redis服務(wù)

    一文詳解如何停止/重啟/啟動Redis服務(wù)

    Redis是當(dāng)前比較熱門的NOSQL系統(tǒng)之一,它是一個key-value存儲系統(tǒng),這篇文章主要給大家介紹了關(guān)于如何停止/重啟/啟動Redis服務(wù)的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-03-03
  • 如何使用Redis實現(xiàn)電商系統(tǒng)的庫存扣減

    如何使用Redis實現(xiàn)電商系統(tǒng)的庫存扣減

    在日常開發(fā)中有很多地方都有類似扣減庫存的操作,本文主要介紹了如何使用Redis實現(xiàn)電商系統(tǒng)的庫存扣減,具有一定的參考價值,感興趣的可以了解一下
    2022-01-01

最新評論

云浮市| 株洲市| 金坛市| 荃湾区| 神农架林区| 长春市| 家居| 东方市| 鄂托克前旗| 临洮县| 红原县| 缙云县| 任丘市| 云南省| 繁峙县| 京山县| 介休市| 佛冈县| 台湾省| 信丰县| 旅游| 东乡县| 蓝田县| 揭阳市| 宣化县| 苍溪县| 博客| 武隆县| 嵊泗县| 四川省| 紫金县| 吉安市| 长白| 康保县| 台南市| 龙川县| 绥阳县| 南康市| 三门峡市| 荃湾区| 湛江市|