3

我正在构建一个带有很多表单的 GWT 应用程序。我正在使用 gwt-platform 及其调度模块。

我的下一步是防止在服务器端重复提交。问题是我不知道该怎么做...

我想到了这样的事情:

  1. 当应用程序加载时,服务器会向客户端提供一些生成的令牌
  2. 服务器将令牌存储在 HTTPSession 中
  3. 当客户端提交表单时,它将从 (1.) 发送令牌以及表单
  4. 服务器检查 HTTPSession 中发送的令牌是否 == 令牌
  5. 在对客户端的回答中,它将发送一个新令牌

将令牌存储在 HTTPSession 中是否安全?或者我应该简单地在服务器上创建一个从 SESSION_ID 映射到生成的令牌的 HashMap?

或者也许已经在 GWT 或 gwt-platform 或其他地方实现了它?

谢谢

4

1 回答 1

5

你首先要问自己的问题是:你想避免什么样的问题场景?

  1. 用户不小心(或出于沮丧,...)单击按钮两次。
  2. 只能使用一次的资源(例如飞机上某个座位的预订)被消耗两次。

不要只说“我想避免两者”。即使这样做,您也必须分别处理这两个问题。

问题 1

这可以在客户端更好地解决(例如,一旦单击按钮就禁用它)。

它也可以在服务器端解决(通过检查序列号或令牌或者可能是内容的哈希码,......),但我真的不明白这一点。如果用户真的想提交两次(例如通过操作 JavaScript 使按钮不会被禁用),那么就让他们:问题 1 与安全性无关。

问题 2

这必须在服务器端解决(除非在非常特殊的情况下)。这主要是关于安全性。但是仔细一想,这个问题并不能通过双重提交预防来解决!为什么不?

让我们看一下我们的示例:飞机上的座位只能预订一次。这可以通过多种方式违反:

  • 通过双重提交。
  • 由同一用户同时提交,例如从不同的浏览器窗口。
  • 由多个用户尝试同时预订。

解决问题的干净方法是通过保留座位以原子方式检查座位的可用性。如果违规是由重复提交引起的,这并不重要(问题 1 涵盖了意外的重复提交)。

...和问题 3

如果你已经实现了一些自动重提交机制,那么你可能还会遇到第三种问题:

假设用户想要将商品添加到他的购物车。客户端提交,超时前未收到来自服务器的响应。所以它会自动再次发送。然而,服务器接收到这两条消息,并尝试同时处理它们——因此它将商品两次添加到购物车中。

在我看来,避免这种情况的最佳解决方案通常不是使用“将一件商品添加到购物车”之类的操作,而是“将商品的目标数量设置为 1”。同样,您也可以使用序列号等。

于 2012-05-21T07:48:18.220 回答