在Spring Boot中,防止接口或表单重复提交有多种策略,以下是几种常见且有效的方案:
-
前端控制:
- 禁用提交按钮:在表单提交后,使用JavaScript立即禁用提交按钮,防止用户再次点击。
- 响应式提示:提交后显示加载提示,同时禁用提交功能,直到得到服务器响应。
-
后端控制:
-
Token机制:
- 一次性Token: 在页面加载时,后端生成一个Token(如UUID)并传给前端,前端提交表单时携带此Token。后端验证Token的有效性并将其标记为已使用,下次再接收到相同的Token则拒绝请求。
- 时间戳+签名: 类似于CSRF Token,但可以结合时间戳和签名机制,确保Token的有效期,并验证请求的新鲜度。
-
Token机制:
-
使用Redis分布式锁:
- 利用用户标识(如用户ID、session ID)与请求URI作为键,尝试获取Redis锁。如果获取成功,则处理请求;处理完毕后释放锁。如果获取失败,说明有其他请求正在处理,直接拒绝本次请求。
-
自定义注解和AOP(面向切面编程):
- 创建一个自定义注解(如
@NoRepeatSubmit
),并编写AOP逻辑来拦截标记了此注解的方法。在方法执行前后,检查请求是否重复,比如通过存储在Redis中的请求标识来判断。
- 创建一个自定义注解(如
-
数据库乐观锁/悲观锁:
- 对于更新操作,可以利用数据库的乐观锁或悲观锁机制来防止并发更新导致的数据不一致问题。
-
使用拦截器(Interceptor):
- 实现一个拦截器,检查请求头或请求体中是否存在防止重复提交的标识(如上述Token),并在服务器端验证其有效性。
-
设置浏览器缓存控制:
- 通过HTTP头部设置如
Cache-Control: no-cache, no-store, must-revalidate
和Pragma: no-cache
,避免因浏览器缓存造成的重复提交。
- 通过HTTP头部设置如
每种方案都有其适用场景,实际应用中可以根据业务需求和系统架构选择合适的策略,甚至组合使用多种方式来增强防护效果。例如,在高并发场景下,结合Redis分布式锁和自定义注解+AOP的方式会更为高效和安全。