使用Token机制
防止表单重复提交是Web开发中常见的需求,以下是综合多种方法的有效解决方案:
一、服务器端防护(推荐)
-
Token机制(Session或Redis)
-
Session方式 :服务器生成唯一Token并存入Session,表单提交时携带该Token,服务器验证Token有效性后删除Session中的Token。
-
Redis方式 :生成分布式Token存入Redis,请求时验证Token是否已存在,避免重复处理。
-
-
数据库约束
- 在数据库表中为关键字段添加唯一约束(如用户名、邮箱等),防止重复数据插入。
-
Post/Redirect/Get模式
- 提交后重定向到成功页面,避免用户刷新或后退导致的重复提交。
-
分布式锁(适用于高并发场景)
- 使用Redis或数据库锁机制,确保同一请求只处理一次。
二、客户端防护(辅助)
-
禁用提交按钮
- 通过JavaScript提交后禁用按钮,防止多次点击。但需注意用户刷新页面会失效。
function disableSubmitButton() { document.getElementById('submitBtn').disabled = true; }
-
防抖处理
- 限制短时间内多次点击,例如设置500ms冷却时间。
三、其他注意事项
-
幂等性设计 :对于API接口,确保多次相同请求只产生一次结果,可通过Token或状态标记实现。
-
异常处理 :捕获重复提交的异常,返回统一提示信息。
四、示例代码(Session Token机制)
后端(Java) :
import javax.servlet.http.*;
import java.util.UUID;
public class TokenUtil {
private static final String TOKEN_PREFIX = "subToken_";
private static final int SESSION_TIMEOUT = 5000; // 5秒
public static String generateToken(HttpServletRequest request) {
String token = UUID.randomUUID().toString();
request.getSession().setAttribute(token, token);
return token;
}
public static boolean validateToken(HttpServletRequest request, String token) {
String sessionToken = (String) request.getSession().getAttribute(token);
return sessionToken != null && sessionToken.equals(token);
}
public static void removeToken(HttpServletRequest request) {
String token = (String) request.getSession().getAttribute("subToken");
if (token != null) {
request.getSession().removeAttribute(token);
}
}
}
前端(JSP) :
<form action="submitForm" method="post">
<input type="hidden" name="subToken" value="${token}" />
<!-- 其他表单字段 -->
<input type="submit" value="提交" onclick="return disableSubmit();" />
</form>
<script>
function disableSubmit() {
document.getElementById('submitBtn').disabled = true;
}
</script>
通过上述方法,可有效防止表单重复提交,提升系统稳定性和用户体验。