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

java實現(xiàn)認證與授權(quán)的jwt與token+redis,哪種方案更好用?

 更新時間:2025年09月27日 14:57:01   作者:程序員小2  
JWT(JSON Web Token)與Token+Redis是兩種常見的用戶認證方案,它們在設(shè)計原理、性能和安全特性上存在顯著差異,JWT為無狀態(tài)認證,適合分布式系統(tǒng)但無法主動失效;Token+Redis依賴Redis存儲會話,支持實時吊銷但運維復(fù)雜,兩者各有優(yōu)劣

JWT(JSON Web Token)與Token+Redis是兩種常見的用戶認證方案,它們在設(shè)計原理、性能和安全特性上存在顯著差異。JWT為無狀態(tài)認證,適合分布式系統(tǒng)但無法主動失效;Token+Redis依賴Redis存儲會話,支持實時吊銷但運維復(fù)雜,兩者各有優(yōu)劣,混合方案結(jié)合短期JWT與Redis黑名單實現(xiàn)安全與便利平衡,推薦根據(jù)業(yè)務(wù)場景靈活選擇。

一、認證與授權(quán)

在深入討論之前,我們先明確兩個基本概念:

  1. 認證(Authentication):你是誰?驗證用戶身份的過程
  2. 授權(quán)(Authorization):你能做什么?驗證用戶權(quán)限的過程

無論是JWT還是Token+Redis,都是用來解決這兩個問題的技術(shù)方案。

二、JWT方案

2.1 JWT是什么?

JWT是一種無狀態(tài)的身份驗證機制,通過將用戶信息編碼在令牌中實現(xiàn)驗證。其核心優(yōu)勢在于分布式友好和性能高,適合微服務(wù)架構(gòu)和跨域SSO場景。但由于無法主動失效Token,存在信息泄露風(fēng)險,且權(quán)限更新需要重新生成Token。

JWT(JSON Web Token)是一種開放標準(RFC 7519),用于在各方之間安全地傳輸信息作為JSON對象。JWT由三部分組成:

header.payload.signature
  • Header:包含令牌類型和簽名算法
  • Payload:包含聲明(用戶信息、過期時間等)
  • Signature:用于驗證消息在傳輸過程中沒有被篡改

2.2 JWT的工作流程

讓我們通過一個完整的登錄流程來理解JWT的工作原理:

2.3 JWT的Java實現(xiàn)示例

下面是一個簡單的JWT工具類實現(xiàn):

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import java.security.Key;
import java.util.Date;

public class JwtUtil {
    // 密鑰,實際項目中應(yīng)從配置中讀取
    private static final Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
    
    // 過期時間:2小時
    private static final long EXPIRATION_TIME = 2 * 60 * 60 * 1000;
    
    /**
     * 生成JWT
     */
    public static String generateToken(String userId, String username, List<String> roles) {
        return Jwts.builder()
                .setSubject(userId)
                .claim("username", username)
                .claim("roles", roles)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                .signWith(key)
                .compact();
    }
    
    /**
     * 驗證并解析JWT
     */
    public static Claims parseToken(String token) {
        try {
            return Jwts.parserBuilder()
                    .setSigningKey(key)
                    .build()
                    .parseClaimsJws(token)
                    .getBody();
        } catch (ExpiredJwtException e) {
            thrownew RuntimeException("Token已過期", e);
        } catch (JwtException e) {
            thrownew RuntimeException("Token無效", e);
        }
    }
    
    /**
     * 刷新Token
     */
    public static String refreshToken(String token) {
        Claims claims = parseToken(token);
        return generateToken(claims.getSubject(), 
                           claims.get("username", String.class), 
                           claims.get("roles", List.class));
    }
}

2.4 JWT的優(yōu)點和缺點

優(yōu)點:

  1. 無狀態(tài):服務(wù)端不需要存儲會話信息
  2. 跨域友好:適合分布式系統(tǒng)和微服務(wù)架構(gòu)
  3. 自包含:令牌中包含所有必要信息
  4. 擴展性好:可以輕松添加自定義聲明

缺點:

  1. 無法主動失效:一旦簽發(fā),在到期前一直有效
  2. 令牌大小:包含的信息越多,令牌越大
  3. 安全性依賴:完全依賴簽名,密鑰泄露后果嚴重

三、Token+Redis方案

3.1 Token+Redis是什么?

該方案通過Redis集中存儲會話信息,具有完全控制會話和動態(tài)權(quán)限管理的優(yōu)勢,可實時吊銷Token或綁定設(shè)備屬性增強安全性。但性能依賴Redis集群,運維復(fù)雜度較高。實現(xiàn)時通常將生成的Token存入Redis并設(shè)置過期時間,結(jié)合攔截器進行雙重驗證(簽名校驗和Redis查詢)。

Token+Redis方案使用隨機生成的令牌作為用戶會話的標識,將會話數(shù)據(jù)存儲在Redis中。

這種方案本質(zhì)上是有狀態(tài)的,服務(wù)端需要維護會話狀態(tài)。

3.2 Token+Redis的工作流程

3.3 Token+Redis的Java實現(xiàn)示例

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Component
public class RedisSessionManager {
    
    private final RedisTemplate<String, Object> redisTemplate;
    
    // 會話過期時間:2小時
    private static final long SESSION_EXPIRE_TIME = 2 * 60 * 60;
    
    public RedisSessionManager(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
    
    /**
     * 創(chuàng)建會話
     */
    public String createSession(User user) {
        String token = generateToken();
        SessionInfo sessionInfo = new SessionInfo(user.getId(), user.getUsername(), user.getRoles());
        
        redisTemplate.opsForValue().set(
            getRedisKey(token), 
            sessionInfo, 
            SESSION_EXPIRE_TIME, 
            TimeUnit.SECONDS
        );
        
        return token;
    }
    
    /**
     * 獲取會話信息
     */
    public SessionInfo getSession(String token) {
        return (SessionInfo) redisTemplate.opsForValue().get(getRedisKey(token));
    }
    
    /**
     * 刪除會話
     */
    public void deleteSession(String token) {
        redisTemplate.delete(getRedisKey(token));
    }
    
    /**
     * 刷新會話有效期
     */
    public void refreshSession(String token) {
        redisTemplate.expire(getRedisKey(token), SESSION_EXPIRE_TIME, TimeUnit.SECONDS);
    }
    
    /**
     * 生成隨機token
     */
    private String generateToken() {
        return UUID.randomUUID().toString().replace("-", "");
    }
    
    /**
     * 獲取Redis key
     */
    private String getRedisKey(String token) {
        return "session:" + token;
    }
    
    /**
     * 會話信息類
     */
    @Data
    @AllArgsConstructor
    public static class SessionInfo {
        private String userId;
        private String username;
        private List<String> roles;
        private long createTime;
        
        public SessionInfo(String userId, String username, List<String> roles) {
            this.userId = userId;
            this.username = username;
            this.roles = roles;
            this.createTime = System.currentTimeMillis();
        }
    }
}

3.4 Token+Redis的優(yōu)點和缺點

優(yōu)點:

  1. 主動控制:可以隨時使特定令牌失效
  2. 信息量小:令牌只是一個標識符,不會太大
  3. 靈活性高:可以存儲復(fù)雜的會話狀態(tài)
  4. 安全性好:令牌泄露可以立即撤銷

缺點:

  1. 有狀態(tài):服務(wù)端需要存儲會話信息
  2. Redis依賴:Redis成為單點故障源
  3. 網(wǎng)絡(luò)開銷:每次請求都需要查詢Redis
  4. 擴展性挑戰(zhàn):需要處理Redis集群和數(shù)據(jù)同步

四、深度對比分析

4.1 性能對比

從性能角度,兩種方案有顯著差異:

方面

JWT

Token+Redis

認證速度

快(本地驗證)

慢(需要Redis查詢)

網(wǎng)絡(luò)開銷

大(每次請求都需要訪問Redis)

服務(wù)端壓力

大(Redis需要處理大量查詢)

擴展成本

高(需要維護Redis集群)

4.2 安全性對比

安全性是認證方案的核心考量因素:

JWT安全性考慮:

  1. 密鑰管理:簽名密鑰需要嚴格保護,定期輪換
  2. 令牌泄露:無法主動失效,只能等待自動過期
  3. 算法選擇:需要選擇安全的簽名算法(如HS256、RS256)

Token+Redis安全性考慮:

  1. Redis安全:需要保證Redis實例的安全性
  2. 令牌隨機性:令牌必須足夠隨機,防止猜測
  3. 傳輸安全:需要HTTPS防止令牌被竊聽

4.3 適用場景對比

不同的業(yè)務(wù)場景適合不同的方案:

適合JWT的場景:

  1. 分布式系統(tǒng)和微服務(wù)架構(gòu)
  2. 需要跨域認證的單頁應(yīng)用(SPA)
  3. 無狀態(tài)API服務(wù)
  4. 移動應(yīng)用后端

適合Token+Redis的場景:

  1. 需要精細控制會話的企業(yè)應(yīng)用
  2. 需要實時吊銷權(quán)限的系統(tǒng)
  3. 會話信息復(fù)雜的傳統(tǒng)Web應(yīng)用
  4. 對安全性要求極高的金融系統(tǒng)

五、混合方案

有些小伙伴在工作中可能會想:能不能結(jié)合兩種方案的優(yōu)點?

答案是肯定的!

下面介紹一種混合方案:

5.1 短期JWT + Redis黑名單

這種方案使用短期有效的JWT,配合Redis黑名單實現(xiàn)主動注銷:

public class HybridAuthManager {
    
    private final JwtUtil jwtUtil;
    private final RedisTemplate<String, Object> redisTemplate;
    
    // JWT短期有效期:15分鐘
    private static final long SHORT_EXPIRATION = 15 * 60 * 1000;
    // 刷新令牌有效期:7天
    private static final long REFRESH_EXPIRATION = 7 * 24 * 60 * 60 * 1000;
    
    /**
     * 生成訪問令牌和刷新令牌
     */
    public AuthResponse generateTokenPair(User user) {
        // 生成短期訪問令牌
        String accessToken = jwtUtil.generateToken(
            user.getId(), user.getUsername(), user.getRoles(), SHORT_EXPIRATION);
        
        // 生成長期刷新令牌
        String refreshToken = UUID.randomUUID().toString();
        
        // 存儲刷新令牌到Redis
        storeRefreshToken(refreshToken, user.getId());
        
        returnnew AuthResponse(accessToken, refreshToken);
    }
    
    /**
     * 刷新訪問令牌
     */
    public String refreshAccessToken(String refreshToken) {
        // 驗證刷新令牌有效性
        String userId = validateRefreshToken(refreshToken);
        if (userId == null) {
            thrownew RuntimeException("刷新令牌無效");
        }
        
        // 獲取用戶信息
        User user = userService.getUserById(userId);
        
        // 生成新的訪問令牌
        return jwtUtil.generateToken(
            user.getId(), user.getUsername(), user.getRoles(), SHORT_EXPIRATION);
    }
    
    /**
     * 注銷令牌
     */
    public void logout(String accessToken, String refreshToken) {
        // 將訪問令牌加入黑名單(剩余有效期內(nèi))
        Claims claims = jwtUtil.parseToken(accessToken);
        long expiration = claims.getExpiration().getTime() - System.currentTimeMillis();
        if (expiration > 0) {
            redisTemplate.opsForValue().set(
                "blacklist:" + accessToken, 
                "logout", 
                expiration, 
                TimeUnit.MILLISECONDS
            );
        }
        
        // 刪除刷新令牌
        if (refreshToken != null) {
            redisTemplate.delete("refresh_token:" + refreshToken);
        }
    }
    
    /**
     * 驗證令牌是否在黑名單中
     */
    public boolean isTokenBlacklisted(String token) {
        return redisTemplate.hasKey("blacklist:" + token);
    }
}

5.2 混合方案工作流程

六、實際項目選型建議

根據(jù)我多年的工作經(jīng)驗,給大家一些實用的選型建議:

6.1 選擇JWT當(dāng)以下情況成立時:

  1. 系統(tǒng)是分布式架構(gòu),需要無狀態(tài)認證。
  2. 需要支持跨域認證(如多個前端應(yīng)用共享后端)。
  3. API消費者主要是第三方應(yīng)用或移動端。
  4. 團隊有能力管理好密鑰和令牌安全。

6.2 選擇Token+Redis當(dāng)以下情況成立時:

  1. 系統(tǒng)是單體或少量服務(wù)的架構(gòu)。
  2. 需要精細的會話控制和實時權(quán)限管理。
  3. 有專業(yè)的運維團隊維護Redis集群。
  4. 對安全性要求極高,需要即時吊銷能力。

6.3 選擇混合方案當(dāng)以下情況成立時:

  1. 既需要JWT的無狀態(tài)特性,又需要主動注銷能力。
  2. 系統(tǒng)對用戶體驗要求高(避免頻繁登錄)。
  3. 有能力處理稍復(fù)雜的令牌管理邏輯。
  4. 需要平衡安全性和便利性。

總結(jié)

通過上面的詳細分析,JWT和token+redis這兩種方案,各有優(yōu)缺點和適用場景。

我們可以得出以下結(jié)論:

  1. 沒有絕對的最好方案:只有最適合具體業(yè)務(wù)場景的方案。
  2. JWT優(yōu)勢在無狀態(tài)和擴展性:適合分布式系統(tǒng)和API優(yōu)先的架構(gòu)。
  3. Token+Redis優(yōu)勢在控制和靈活性:適合需要精細會話管理的企業(yè)應(yīng)用。
  4. 混合方案取長補短:適合大多數(shù)現(xiàn)代Web應(yīng)用。

有些小伙伴在工作中可能會盲目追求技術(shù)的新穎性,或者過度設(shè)計認證方案。

我的建議是:從實際業(yè)務(wù)需求出發(fā),選擇最簡單可靠的方案

對于大多數(shù)應(yīng)用來說,我推薦采用混合方案:

  • 使用短期JWT保證API的無狀態(tài)特性。
  • 使用刷新令牌機制優(yōu)化用戶體驗。
  • 使用Redis黑名單提供主動注銷能力。
  • 使用HTTPS和嚴格的密鑰管理保證安全性。

無論選擇哪種方案,都要記?。喊踩皇且粋€功能,而是一個過程。

到此這篇關(guān)于java實現(xiàn)認證與授權(quán)的jwt與token+redis,哪種方案更好用?的文章就介紹到這了,更多相關(guān)java實現(xiàn)認證與授權(quán)的jwt與token+redis內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 深入理解窗口令牌WindowToken

    深入理解窗口令牌WindowToken

    這篇文章主要介紹了窗口令牌WindowToken的概念與作用,它是對應(yīng)用組件的行為進行規(guī)范管理的一個手段。WindowToken由應(yīng)用組件或其管理者負責(zé)向WMS聲明并持有
    2021-08-08
  • Spring對象創(chuàng)建范式的五大適用場景詳解

    Spring對象創(chuàng)建范式的五大適用場景詳解

    本文深度解析了Spring中依賴注入與直接實例化的決策邊界,破除“萬物皆Bean”誤區(qū),文章系統(tǒng)梳理了五大適合直接new的場景,希望對大家有所幫助
    2026-06-06
  • Java實現(xiàn)八種排序算法詳細代碼舉例

    Java實現(xiàn)八種排序算法詳細代碼舉例

    排序問題一直是程序員工作與面試的重點,今天特意整理研究下與大家共勉!這篇文章主要介紹了Java實現(xiàn)八種排序算法的相關(guān)資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-10-10
  • Java構(gòu)建乘積數(shù)組的方法

    Java構(gòu)建乘積數(shù)組的方法

    這篇文章主要為大家詳細介紹了Java構(gòu)建乘積數(shù)組的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-03-03
  • JAVA實現(xiàn)簡單系統(tǒng)登陸注冊模塊

    JAVA實現(xiàn)簡單系統(tǒng)登陸注冊模塊

    這篇文章主要介紹了一個簡單完整的登陸注冊模塊的實現(xiàn)過程,文章條理清晰,在實現(xiàn)過程中加深了對相關(guān)概念的理解,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2015-07-07
  • SPRING IOC注入方式過程解析

    SPRING IOC注入方式過程解析

    這篇文章主要介紹了SPRING IOC注入方式過程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-01-01
  • Spring Security 安全認證的示例代碼

    Spring Security 安全認證的示例代碼

    這篇文章主要介紹了Spring Security 安全認證的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • java 單例模式(懶漢式與餓漢式)

    java 單例模式(懶漢式與餓漢式)

    這篇文章主要介紹了java 單例模式的相關(guān)資料,這里對懶漢式與餓漢式都做了實例介紹,需要的朋友可以參考下
    2017-07-07
  • Java Arrays.fill()的具體使用

    Java Arrays.fill()的具體使用

    本文主要介紹了Java Arrays.fill()的具體使用,更好地理解Arrays.fill()方法的用法以及在實際應(yīng)用中如何使用它,感興趣的可以了解一下
    2023-09-09
  • Java生成唯一訂單號的幾種方式

    Java生成唯一訂單號的幾種方式

    這篇文章主要介紹了Java生成唯一訂單號的幾種方式,訂單號具有唯一標識符的作用,下邊將演示自增、隨機、組合的方式,生成高效、安全、唯一的訂單號,以滿足業(yè)務(wù)需求和避免潛在問題,需要的朋友可以參考下
    2025-03-03

最新評論

玉溪市| 宁河县| 陆良县| 泸州市| 石柱| 佳木斯市| 禹州市| 贺州市| 蓝山县| 阜南县| 宁阳县| 保德县| 廉江市| 东乌珠穆沁旗| 集安市| 临沂市| 丹巴县| 塘沽区| 邵阳县| 汾西县| 澎湖县| 南丰县| 册亨县| 河东区| 任丘市| 霍山县| 陈巴尔虎旗| 湖州市| 阳泉市| 鸡西市| 和政县| 长顺县| 凌云县| 金堂县| 东兰县| 沛县| 桑日县| 独山县| 道真| 临沂市| 灌阳县|