接口优化方向
秒杀临时地址设计方案
1. 整体架构设计
前端交互流程:
用户点击秒杀 → 获取临时地址 → 使用临时地址秒杀 → 后端验证 → 执行秒杀逻辑
2. 接口设计
2.1 生成临时秒杀地址接口
- 接口路径 : /seckill/path
- 请求方式 :GET
- 参数 : goodsId (商品ID)
- 返回 :临时秒杀地址字符串
- 逻辑流程 :
- 检查用户登录状态
- 生成随机秒杀路径(UUID)
- 存储到Redis: seckill:path:{userId}:{goodsId} = 随机路径
- 设置60秒过期时间
- 返回临时地址 2.2 修改doSeckill2接口
- 新增参数 : path (临时秒杀地址)
- 验证逻辑 :
- 从Redis获取存储的临时地址
- 验证传入的path是否匹配
- 验证通过后删除Redis中的临时地址(防止重复使用)
- 继续原有的秒杀逻辑
3. Redis数据结构设计
Key格式:seckill:path:{userId}:{goodsId}
Value:随机生成的秒杀路径(如:a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4)
过期时间:60秒
4. 临时地址生成策略
// 生成策略
String path = UUID.randomUUID().toString().replace("-", "");
// 或者更复杂的组合
String path = MD5Util.md5(userId + goodsId + timestamp +
randomSalt);
5. 安全性考虑
- 时效性 :60秒过期,防止长时间有效
- 一次性使用 :验证后立即删除Redis中的临时地址
- 用户绑定 :临时地址与用户ID和商品ID绑定
- 随机性 :使用UUID或MD5确保不可预测
- 防重放 :验证后删除,防止重复使用
6. 前端调用示例
// 1. 获取临时秒杀地址
fetch('/seckill/path?goodsId=1')
.then(response => response.json())
.then(data => {
if (data.code === 200) {
const tempPath = data.data;
// 2. 使用临时地址进行秒杀
return fetch(`/seckill/doSeckill2?goodsId=1&path=$
{tempPath}`);
}
})
.then(response => response.json())
.then(data => {
// 处理秒杀结果
});
7. 错误处理
错误场景 错误码 错误信息 未登录 500210 SESSION_ERROR 临时地址不存在 400214 PATH_NOT_EXIST 临时地址已过期 400215 PATH_EXPIRED 临时地址已使用 400216 PATH_ALREADY_USED
8. 优势
- 隐藏真实接口 :前端无法直接访问doSeckill2
- 防止恶意攻击 :没有有效临时地址无法秒杀
- 时间控制 :60秒有效窗口期
- 用户绑定 :临时地址与用户和商品绑定
- 性能优化 :Redis验证,高效快速
9. 实现细节
9.1 临时地址生成
@RequestMapping("/path")
public CommonResult<String> getSeckillPath(TUser user, Long
goodsId) {
// 1. 检查登录
if (user == null) {
return CommonResult.error(ResponseCode.SESSION_ERROR);
}
// 2. 生成随机路径
String path = UUID.randomUUID().toString().replace("-",
"");
// 3. 存储到Redis,60秒过期
String key = "seckill:path:" + user.getId() + ":" +
goodsId;
redisTemplate.opsForValue().set(key, path, 60, TimeUnit.
SECONDS);
// 4. 返回临时地址
return CommonResult.success(path);
}
9.2 doSeckill2验证逻辑
@RequestMapping("/doSeckill2")
@RateLimit(seconds = 5, maxCount = 5, limitType = RateLimit.
LimitType.USER_ID)
public CommonResult<Integer> doSeckill2(TUser user, Long
goodsId, String path) {
// 1. 检查登录
if (user == null) {
return CommonResult.error(ResponseCode.SESSION_ERROR);
}
// 2. 验证临时地址
String key = "seckill:path:" + user.getId() + ":" +
goodsId;
String storedPath = (String) redisTemplate.opsForValue().
get(key);
if (storedPath == null) {
return CommonResult.error(ResponseCode.PATH_NOT_EXIST);
}
if (!storedPath.equals(path)) {
return CommonResult.error(ResponseCode.PATH_INVALID);
}
// 3. 删除临时地址(防止重复使用)
redisTemplate.delete(key);
// 4. 继续原有的秒杀逻辑
// ... 原有逻辑 ...
}
10. 需要添加的响应码
PATH_NOT_EXIST(400214,"秒杀地址不存在"),
PATH_EXPIRED(400215,"秒杀地址已过期"),
PATH_ALREADY_USED(400216,"秒杀地址已使用"),
PATH_INVALID(400217,"秒杀地址无效")
总结
这个方案通过临时地址机制有效保护了真正的秒杀接口,防止了恶意攻击和直接访问,同时保持了良好的用户体验。60秒的有效期既保证了安全性,又给用户足够的时间完成秒杀操作。
518




被折叠的 条评论
为什么被折叠?



