假设您正在提交一个表单,这会影响您的数据库(添加记录/删除记录/更新记录),您的请求如下所示:

POST /应用程序/操作=更新

现在,假设您已完成更新,因此您希望将用户带到主页。

Response.sendRedirect /application/action=home

这效果非常好。POST 后会向用户发送重定向,因此即使用户尝试按 F5 刷新页面,也没有问题。但是,如果您这样做,这将不起作用:

requestDispatcher.forward(/application/action=home)

考虑到在完成更新后必须显示不同类型的错误/成功消息的情况,您很可能在 POST 之后执行转发。在这种情况下,如何避免更新操作发生两次?

我觉得很有趣的是,许多安全网站(银行)/支付网关倾向于通过在屏幕上放置文本来通知用户,例如“请不要按后退/刷新按钮”。

有没有更好的方法来处理这个问题?除了要求用户不要按这些按钮之外?当我上次检查时,有一个叫做“垂直响应缓存”的东西。一个过滤器,用于识别会话中请求的唯一性,并在请求重复时尝试发送缓存的响应。有没有更简单的方法来解决这个经典问题?

这是我正在讨论的垂直响应缓存解决方案的链接: http://www.fingo.info/en/articles/_1.html. 。然而,我不确定这到底有多有效。

有帮助吗?

解决方案

,我已经有一个想法是嵌入一个唯一的ID(可能是随机的字符串),为隐藏的表单字段中正在被POST提交的形式。该ID字符串可以把数据库中的“事务ID”。现在,当你去更新数据库,首先检查是否有与所提交的事务ID现有的记录,如果是这样,假设它是一个重复的,不更改数据库。

当然,正如我所说,这仅仅是一个想法。我不知道有什么方法在实践中实际使用。 (我怀疑少了很多关键部位只是忽略的问题,并希望他们的用户将智能...如果我见过一个亏本生意; - )

修改的:如在评论中指出,在数据库中存储事务ID可能会占用大量的空间,但如果这是一个问题,你可以保持所有事务的内存缓存在最后5分钟的处理IDS / 1小时/ 1天/不管。这应该工作,除非你面对一个意志坚定的黑客...

其他提示

是的,我相信你应该在POST之后重定向,与API请求的除外。如果不这样做,你不仅不必担心越来越重复的文章,当用户使用后退按钮,但浏览器也将带给用户烦人的对话框时,他们尝试使用后退按钮。

response.sendRedirect是工作在实践中,但tecnically上讲这是发出错误的HTTP响应代码用于此目的。的sendRedirect发送一个302,但正确的代码使用一个POST转换成GET是303(大多数浏览器将把302就像303,如果他们得到它响应POST,但是)

在一般你想重定向到用户发送到任何视图将显示其变化的影响。举例来说,如果他们编辑控件,他们应该被重定向到一个小部件的视图。如果他们删除一个小部件,它们应该被重定向到认为小部件会出现在当它存在(或许窗列表)。

有时很不错的状态消息进一步推动家庭发生了作用的事实。一个简单的方法来做到这一点是有你的观点,即,当设置时,会显示一个动作完成消息的通用参数。例如:

/widget?id=12345&msg=Widget+modified.

下面的“msg”中参数包含消息“窗口小部件修饰的”。一个缺点这种方法的缺点是有可能的恶意网站给你的用户感到迷惑/误解的消息。例如:

/account?msg=Foo+Corp.+hates+you.

如果你真的担心这一点,你可能包括该消息作为附加参数的过期签名。如果签名无效或已过期,根本不显示该消息。

要解决表示POST后状态消息发送到用户获得重定向的问题的最佳解决方案是使用用户会话。

如何

与值将属性添加到用户会话作为要显示的消息的集合。对于如。

userSession.put("success_messages", new HashSet<String>(){"Success", "Check your account balance"});
userSession.put("warning_messages", new HashSet<String>(){"Your account balance is low. Recharge immediately"});

和具有过滤器,其扫描这些特定属性的用户会话并输出该消息。作为状态消息通常只显示一次读数一次,后过滤器应删除的属性。

我觉得相当有趣,很多安全网站(银行)/支付网关往往放置在屏幕上的文字,比如“请不要按后退/刷新按钮”,以通知用户。

有些人觉得它不如“禁用所有后退,刷新事件在这个关键页”; 我不知道这是好还是不好。

但你的处理解决方案 “的垂直响应缓存” 听起来不错

它有点不明显,但是:

  • 在用户会话中创建一个键控对象。
  • 该值是结果的 Request + java Future
  • 通过客户端重定向立即返回。
  • 在处理客户端重定向时,让工作线程负责生成答案。

因此,当客户端浏览器完成重定向、获取新页面的图像等时......结果正在等待用户。

另一种方法是让用户痛苦地意识到数据库花费了多长时间。

安全更新(2011 年 1 月 24 日):

该密钥容易受到攻击,因为它是对客户端的响应的一部分,因此

  1. 生成随机密钥
  2. 使用用户的会话 ID 作为盐来创建 SHA-1
  3. 将随机密钥和 SHA-1 存储在数据库中,并以 (, ) 作为主键。(RANDOMKEY 上没有单独的索引。
  4. 使用 RANDOMKEY 和 SHA-1 作为数据库查找。
  5. 不存储会话 ID(避免能够将多个条目关联到同一用户的隐私问题)
  6. 结果将在 2-3 天后过期。(允许每日批处理作业进行清理,并避免给半持久的用户会话带来问题)

此方法要求任何黑客都知道会话 ID 和随机密钥。

这种方法可能看起来有些过分,但重定向强化机制可用于密码重置等情况。

如果您正在使用Java服务器端脚本工作,也用struts 2,那么你参考这个链接,谈到使用令牌。

http://www.xinotes.org/notes/note/369/

一个令牌应该生成并保存在会话初始页面呈现,当该请求被沿着与令牌提交的第一次,在支柱作用运行带有螺纹名称的线程作为令牌ID和运行该逻辑任何所述客户端已请求,当客户端再次提交相同的请求,检查线程是否仍在运行(thread.getcurrentthread()。打断)如果仍在运行然后发送一个客户端重定向503。

请看看支柱2code的ExecuteAndWaitInterceptor,这与令牌结合逻辑将助阵快点击

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top