侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论

高并发场景下如何设计支持幂等性和防重放攻击的Spring MVC接口

2025-12-13 / 0 评论 / 4 阅读

题目

高并发场景下如何设计支持幂等性和防重放攻击的Spring MVC接口

信息

  • 类型:问答
  • 难度:⭐⭐⭐

考点

Spring MVC请求处理流程, 分布式锁实现, 幂等性设计, 防重放攻击, 高并发优化

快速回答

实现要点:

  • 使用唯一请求ID配合Redis分布式锁保证并发幂等性
  • 通过时间戳+签名机制防御重放攻击
  • 采用二级缓存策略(内存缓存+Redis)优化性能
  • 使用异步处理分离核心业务逻辑
  • 实现自动清理机制防止存储膨胀
## 解析

1. 核心问题分析

在高并发场景下需同时解决:
幂等性 - 相同请求多次执行结果一致
防重放 - 阻止恶意重复提交历史请求
性能 - 高并发下保持系统稳定

2. 架构设计

@RestController
public class PaymentController {
    @PostMapping("/pay")
    public ResponseEntity<?> processPayment(
            @RequestHeader("X-Request-ID") String requestId,
            @RequestHeader("X-Timestamp") long timestamp,
            @RequestHeader("X-Signature") String signature,
            @RequestBody PaymentRequest request) {
        // 1. 验证时间戳和签名
        // 2. 检查请求ID是否已存在
        // 3. 获取分布式锁
        // 4. 执行业务逻辑
    }
}

3. 关键技术实现

3.1 防重放攻击

// 时间窗口验证(5分钟)
if (System.currentTimeMillis() - timestamp > 300_000) {
    throw new ReplayAttackException("Expired request");
}

// 签名验证(HMAC-SHA256)
String computedSig = HmacUtils.hmacSha256Hex(API_SECRET, requestId + timestamp);
if (!computedSig.equals(signature)) {
    throw new SecurityException("Invalid signature");
}

3.2 幂等性保障

// 使用Redisson实现分布式锁
RLock lock = redissonClient.getLock("IDEMPOTENT_LOCK:" + requestId);
try {
    if (!lock.tryLock(0, 5, TimeUnit.SECONDS)) {
        throw new ConcurrentAccessException("Request processing");
    }

    // 检查请求ID是否存在(二级缓存优化)
    if (idempotencyCache.contains(requestId)) {
        return previousResponse; // 返回缓存结果
    }

    // 执行业务逻辑
    PaymentResponse response = paymentService.process(request);

    // 缓存结果(设置TTL)
    idempotencyCache.put(requestId, response, 24, TimeUnit.HOURS);

} finally {
    lock.unlock();
}

3.3 高并发优化

  • 二级缓存结构:Caffeine本地缓存(1秒)+ Redis分布式缓存
  • 异步处理
    @Async注解分离非核心逻辑(如日志记录)
  • 限流机制
    在Controller层添加@RateLimiter注解

4. 最佳实践

  • 请求ID生成:客户端使用UUIDv4或雪花算法
  • 时钟同步:部署NTP服务保证服务器时间一致
  • 密钥管理:使用KMS轮转API密钥
  • 缓存清理:定时任务清理过期请求记录

5. 常见错误

  • 锁超时问题:业务执行时间 > 锁超时时间导致并发穿透
  • 缓存穿透:恶意伪造requestId耗尽存储
  • 时间窗口漏洞:未校验时间戳顺序导致重放
  • 签名缺陷:未包含关键参数导致篡改攻击

6. 扩展知识

  • 分布式锁进阶:RedLock算法 vs Zookeeper顺序节点
  • 性能压测:使用JMeter模拟万级并发验证方案
  • 替代方案:基于数据库唯一索引实现幂等(需考虑分库分表)
  • Spring集成:自定义@Idempotent注解+AOP统一处理