成人免费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-06-02 10:52:11

Android BroadCast 黑名單

2011-01-21 17:53:44

Zimbra

2023-08-31 08:34:07

Users對象序列化

2015-06-04 11:11:15

2013-08-27 10:56:24

2023-08-29 08:00:38

2018-03-12 10:45:41

2021-08-02 12:50:45

sessiontokenJava

2022-04-11 07:34:46

OAuth2UAA節點

2010-11-11 13:20:41

2010-05-24 13:36:11

2011-03-18 13:14:01

2011-07-28 11:10:58

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系統運維

2012-11-23 10:15:06

2010-01-21 11:44:41

垃圾郵件實時黑名單技術

2009-05-14 09:11:49

歐盟反壟斷黑名單
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 一级黄色在线 | 亚洲成av人片在线观看 | 亚洲高清视频一区二区 | 久久网一区二区 | 日韩成人免费av | 亚洲精品久久久久久一区二区 | 精品综合在线 | av在线视 | 国产国拍亚洲精品av | 亚洲综合中文字幕在线观看 | 免费在线看a | 污污的网站在线观看 | 狠狠躁天天躁夜夜躁婷婷老牛影视 | 欧美国产日韩在线观看 | 日韩在线一区二区三区 | 毛色毛片免费看 | 成年人在线观看视频 | 成人超碰 | 久久国产精品久久久久久久久久 | 中文字幕视频在线观看免费 | 免费黄色大片 | 国产精品麻 | 黄色av免费网站 | 久久一日本道色综合久久 | 亚洲精品久久视频 | 亚洲欧美一区在线 | 日本福利视频免费观看 | 成人精品鲁一区一区二区 | 国产精品综合一区二区 | 成人在线国产 | 91 中文字幕| 国产亚洲精品精品国产亚洲综合 | 欧美一区二 | 成人国产精品久久 | 在线一区二区观看 | 国产欧美一区二区三区久久人妖 | 久久久一二三 | 国产午夜精品一区二区 | 视频国产一区 | 国产91丝袜在线播放 | 中文欧美日韩 |