成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Serverless 安全增強篇:整合 OAuth2 + Token 黑名單 + Redis 緩存機制

數據庫 Redis
隨著 Serverless 架構的廣泛應用,傳統 Web 應用中依賴 Session 的認證模式面臨重大挑戰。本文將以 Spring Security 為核心,構建一套無狀態、可擴展、支持 OAuth2、JWT、Redis 黑名單與 Refresh Token 的安全認證體系,適用于 Serverless 應用場景。

隨著 Serverless 架構的廣泛應用,傳統 Web 應用中依賴 Session 的認證模式面臨重大挑戰。本文將以 Spring Security 為核心,構建一套無狀態、可擴展、支持 OAuth2、JWT、Redis 黑名單與 Refresh Token 的安全認證體系,適用于 Serverless 應用場景。

Serverless 應用的安全挑戰

Serverless 應用的無狀態特性決定了其認證模型不能依賴傳統的會話管理。核心挑戰包括:

  • 身份認證用戶身份需要跨請求驗證,無 Session。
  • 權限校驗如何高效識別用戶角色與權限。
  • Token 生命周期管理訪問令牌的過期續簽、注銷。
  • 密鑰管理JWT 簽名密鑰的安全管理。

Spring Security + JWT 構建輕量認證模型

我們采用如下組件構建無狀態認證體系:

組件

作用

JWT

用戶身份令牌,無狀態傳遞

OAuth2

多客戶端支持與統一授權

Redis

黑名單 + RefreshToken 存儲

Spring Security

安全攔截器與權限控制

系統結構設計圖

+-----------------------------+
|        前端調用接口         |
+-----------------------------+
             |
             v
+-----------------------------+
|   API網關 / Serverless函數   |
+-----------------------------+
             |
             v
+-----------------------------+
|  Spring Security + Token攔截 |
+-----------------------------+
             |
             v
+------------+   Redis   +-------------+
| JWT Token校驗 | <----> | Token黑名單 |
+------------+           +-------------+
             |
             v
    +--------------------------+
    |     用戶業務邏輯處理      |
    +--------------------------+

關鍵模塊代碼實現

Spring Boot 啟動類

@SpringBootApplication
public class ServerlessSecurityApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServerlessSecurityApplication.class, args);
    }
}

Security 配置類(無狀態、JWT、資源服務器)

@Configuration
@EnableWebSecurity
public class SecurityConfig {


    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
                .csrf(csrf -> csrf.disable())
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers(\"/api/public/**\", \"/api/token/refresh\").permitAll()
                        .anyRequest().authenticated())
                .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()))
                .build();
    }
}

JWT 工具類

public class JwtUtils {


    private static final Key key = Keys.hmacShaKeyFor(\"0123456789abcdef0123456789abcdef\".getBytes());


    public static String generateAccessToken(String username, String roles, String jti) {
        return Jwts.builder()
                .setSubject(username)
                .setId(jti)
                .claim(\"roles\", roles)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + 3600_000)) // 1小時
                .signWith(key)
                .compact();
    }


    public static String generateRefreshToken(String username, String jti) {
        return Jwts.builder()
                .setSubject(username)
                .setId(jti)
                .claim(\"type\", \"refresh\")
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + 7 * 24 * 3600_000)) // 7天
                .signWith(key)
                .compact();
    }


    public static Claims getClaims(String token) throws JwtException {
        return Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(token)
                .getBody();
    }
}

Redis Token 黑名單工具類

@Component
public class TokenBlacklistUtil {


    private final StringRedisTemplate redisTemplate;


    public TokenBlacklistUtil(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }


    public void blacklistToken(String jti, long ttlSeconds) {
        redisTemplate.opsForValue().set(\"blacklist:\" + jti, \"1\", ttlSeconds, TimeUnit.SECONDS);
    }


    public boolean isTokenBlacklisted(String jti) {
        return redisTemplate.hasKey(\"blacklist:\" + jti);
    }
}

RefreshToken 存儲與刷新接口

@RestController
@RequestMapping(\"/api/token\")
public class TokenController {


    @Autowired
    private StringRedisTemplate redisTemplate;


    @PostMapping(\"/refresh\")
    public ResponseEntity<?> refresh(@RequestParam String refreshToken) {
        Claims claims = JwtUtils.getClaims(refreshToken);
        String jti = claims.getId();
        String username = claims.getSubject();


        // 校驗類型與黑名單
        if (!\"refresh\".equals(claims.get(\"type\"))) {
            return ResponseEntity.badRequest().body(\"非法 token 類型\");
        }


        if (!Boolean.TRUE.equals(redisTemplate.hasKey(\"refresh:\" + jti))) {
            return ResponseEntity.status(401).body(\"refreshToken 已失效\");
        }


        // 生成新 token
        String newJti = UUID.randomUUID().toString();
        String newAccessToken = JwtUtils.generateAccessToken(username, \"USER\", newJti);


        return ResponseEntity.ok(Map.of(\"accessToken\", newAccessToken));
    }
}

登錄、退出控制器(模擬)

@RestController
@RequestMapping(\"/api/auth\")
public class AuthController {


    @Autowired
    private StringRedisTemplate redisTemplate;


    @Autowired
    private TokenBlacklistUtil blacklistUtil;


    @PostMapping(\"/login\")
    public Map<String, String> login(@RequestParam String username) {
        String jti = UUID.randomUUID().toString();
        String accessToken = JwtUtils.generateAccessToken(username, \"USER\", jti);
        String refreshToken = JwtUtils.generateRefreshToken(username, jti);


        // 保存 refreshToken 到 redis
        redisTemplate.opsForValue().set(\"refresh:\" + jti, username, 7, TimeUnit.DAYS);


        return Map.of(\"accessToken\", accessToken, \"refreshToken\", refreshToken);
    }


    @PostMapping(\"/logout\")
    public ResponseEntity<Void> logout(@RequestHeader(\"Authorization\") String authHeader) {
        String token = authHeader.replace(\"Bearer \", \"\");
        Claims claims = JwtUtils.getClaims(token);
        String jti = claims.getId();
        long remaining = (claims.getExpiration().getTime() - System.currentTimeMillis()) / 1000;
        blacklistUtil.blacklistToken(jti, remaining);


        // 同時清除 refreshToken
        redisTemplate.delete(\"refresh:\" + jti);
        return ResponseEntity.ok().build();
    }
}

application.yml 配置

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: https://auth.icoderoad.com/oauth2
          jwk-set-uri: https://auth.icoderoad.com/oauth2/jwks
  redis:
    host: localhost
    port: 6379

總結

無狀態 Serverless 環境下,Spring Security 可通過 JWT、OAuth2 與 Redis 輕松實現高效認證體系:

  • 不依賴 Session
  • 支持訪問控制 + 黑名單管理
  • Refresh Token 保證登錄體驗
  • Redis 做 Token 生命周期緩存

今天就講到這里,如果有問題需要咨詢,大家可以直接留言或掃下方二維碼來知識星球找我,我們會盡力為你解答。

責任編輯:武曉燕 來源: 路條編程
相關推薦

2011-01-21 17:53:44

Zimbra

2011-06-02 10:52:11

Android BroadCast 黑名單

2023-08-29 08:00:38

2023-08-31 08:34:07

Users對象序列化

2015-06-04 11:11:15

2013-08-27 10:56:24

2021-08-02 12:50:45

sessiontokenJava

2018-03-12 10:45:41

2010-11-11 13:20:41

2022-04-11 07:34:46

OAuth2UAA節點

2010-05-24 13:36:11

2018-06-10 09:04:28

2009-10-29 08:39:14

Windows 7系統激活

2019-07-29 08:41:33

算法黑名單ip

2020-07-15 20:32:45

fail2banFirewallD系統運維

2011-03-18 13:14:01

2011-07-28 11:10:58

2010-01-21 11:44:41

垃圾郵件實時黑名單技術

2009-05-14 09:11:49

歐盟反壟斷黑名單

2010-11-01 09:17:21

超級黑名單騰訊QQ360安全中心
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲人人 | 成人免费看 | 国产日屁 | 久久久精 | 国产精品国产三级国产aⅴ无密码 | 人人看人人草 | 日本xx视频免费观看 | 国产高清在线观看 | 精品一区国产 | 国产三区精品 | 国产精品精品久久久久久 | 成人av在线播放 | 日韩精品a在线观看图片 | 久久亚洲国产 | 国产不卡在线播放 | 欧美操操操 | 青青草一区 | 国产在线观看不卡一区二区三区 | 99精品久久久 | 91精品国产一区二区在线观看 | 粉嫩一区二区三区四区公司1 | 国产视频三级 | 伊人伊人| 国产一区二区在线视频 | 欧美极品在线视频 | 日本精品视频一区二区三区四区 | 先锋资源吧 | 欧美一级欧美三级在线观看 | 亚洲日本三级 | 91麻豆精品国产91久久久久久久久 | 国产在线观看一区二区三区 | 色播99 | 国产精品久久久久久久久图文区 | 日韩精品在线免费观看 | 在线中文字幕日韩 | 精品入口麻豆88视频 | 精品乱码一区二区 | 伊人伊人伊人 | 亚洲国产一区二区在线 | 国产精品免费在线 | 亚洲日韩中文字幕一区 |