偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

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

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

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

Serverless 應(yīng)用的安全挑戰(zhàn)

Serverless 應(yīng)用的無狀態(tài)特性決定了其認證模型不能依賴傳統(tǒng)的會話管理。核心挑戰(zhàn)包括:

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

Spring Security + JWT 構(gòu)建輕量認證模型

我們采用如下組件構(gòu)建無狀態(tài)認證體系:

組件

作用

JWT

用戶身份令牌,無狀態(tài)傳遞

OAuth2

多客戶端支持與統(tǒng)一授權(quán)

Redis

黑名單 + RefreshToken 存儲

Spring Security

安全攔截器與權(quán)限控制

系統(tǒng)結(jié)構(gòu)設(shè)計圖

+-----------------------------+
|        前端調(diào)用接口         |
+-----------------------------+
             |
             v
+-----------------------------+
|   API網(wǎng)關(guān) / Serverless函數(shù)   |
+-----------------------------+
             |
             v
+-----------------------------+
|  Spring Security + Token攔截 |
+-----------------------------+
             |
             v
+------------+   Redis   +-------------+
| JWT Token校驗 | <----> | Token黑名單 |
+------------+           +-------------+
             |
             v
    +--------------------------+
    |     用戶業(yè)務(wù)邏輯處理      |
    +--------------------------+

關(guān)鍵模塊代碼實現(xiàn)

Spring Boot 啟動類

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

Security 配置類(無狀態(tài)、JWT、資源服務(wù)器)

@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

總結(jié)

無狀態(tài) Serverless 環(huán)境下,Spring Security 可通過 JWT、OAuth2 與 Redis 輕松實現(xiàn)高效認證體系:

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

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

責任編輯:武曉燕 來源: 路條編程
相關(guān)推薦

2011-06-02 10:52:11

Android BroadCast 黑名單

2011-01-21 17:53:44

Zimbra

2023-08-31 08:34:07

Users對象序列化

2023-08-29 08:00:38

2013-08-27 10:56:24

2015-06-04 11:11:15

2021-08-02 12:50:45

sessiontokenJava

2018-03-12 10:45:41

2022-04-11 07:34:46

OAuth2UAA節(jié)點

2010-11-11 13:20:41

2010-05-24 13:36:11

2011-07-28 11:10:58

2011-03-18 13:14:01

2009-10-29 08:39:14

Windows 7系統(tǒng)激活

2018-06-10 09:04:28

2019-07-29 08:41:33

算法黑名單ip

2020-07-15 20:32:45

fail2banFirewallD系統(tǒng)運維

2020-01-10 15:42:13

SpringBootRedis數(shù)據(jù)庫

2012-11-23 10:15:06

2014-06-06 09:38:22

工信部應(yīng)用軟件黑名單
點贊
收藏

51CTO技術(shù)棧公眾號