19

我正在开发一个 Web 应用程序 (J2EE),我想知道可用于处理来自浏览器的双重发布的选项。

我过去看到和使用的解决方案都是客户端的:

  • 用户单击后立即禁用提交按钮。
  • 遵循 POST-Redirect-GET 模式以防止用户单击后退按钮时出现 POST。
  • 处理表单的 onSubmit 事件并使用 JavaScript 跟踪提交状态。

如果可能,我更愿意实施服务器端解决方案。有没有比我上面提到的更好的方法,或者客户端解决方案是最好的?

4

7 回答 7

11

很难实施防白痴的解决方案(因为他们一直在改进白痴)。 无论您做什么,客户端都可能被操纵或执行不正确。

您的解决方案必须在服务器端才能可靠和安全。 也就是说,一种方法是查看请求并检查系统/数据库状态或日志以确定它是否已被处理。理想情况下,如果可能,服务器端的进程应该是幂等的,如果不能,它必须防止重复提交。

于 2008-09-24T22:38:43.640 回答
9

您可以提供一个“票”作为表单的一部分,一些随机数 - 并确保它不会在服务器端被接受两次。

于 2008-09-24T22:35:57.890 回答
4

想到了两个服务器端解决方案:

  1. 在隐藏的表单字段中创建一次性使用“令牌”。使用令牌后,它将从您存储它的任何数据库或会话上下文对象中删除。第二次,它不被接受。
  2. 缓存收到的信息,如果在某个时间段(10 分钟?一个小时?你决定!)内收到相同的表格,它会被忽略。
于 2008-09-24T22:36:58.810 回答
3

我们使用时间敏感的一次性票。这就像一个会话ID。但它与表单/页面相关联。

当用户提交页面时,您丢弃票证,并且您只处理带有有效票证的页面。同时,您可以通过将票证附加到用户来加强安全性,因此,如果收到的票证是由不是提交票证的用户的用户提交的,您将拒绝该请求。

于 2008-09-24T22:40:03.763 回答
2

实现一个 uniqueid 来处理请求并将其与执行一起记录。如果该 id 已被记录,则您不再执行此工作。这有点像后备解决方案 - 您应该尝试禁用按钮或链接客户端以及您自己的建议

于 2008-09-24T22:37:19.590 回答
2

如果你碰巧在使用 Struts,它就内置了类似的东西。

http://struts.apache.org/1.x/apidocs/org/apache/struts/util/TokenProcessor.html

于 2008-09-25T03:10:58.963 回答
-2

我会使用时间戳并将值与您的服务器端代码进行比较。如果两个时间戳足够接近并且具有相同的 IP 地址,则忽略第二个表单提交。

于 2008-09-24T22:37:20.540 回答