有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java发布后你总是重定向吗?如果是,您如何管理它?

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

发布/应用/操作=更新

现在,比方说,您已经完成了更新,因此您希望将用户带到主页

答复。sendRedirect/application/action=home

这非常有效。POST后会向用户发送重定向,因此即使用户试图通过按F5刷新页面,您也可以。但是,如果您执行以下操作,则此操作将不起作用:

请求调度器。转发(/application/action=home)

假设有这样一种情况,即在完成更新后,您必须显示不同类型的错误/成功消息,那么您很可能是在发布后转发。在这种情况下,如何避免更新操作发生两次

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

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

下面是我所说的垂直响应缓存解决方案的链接:http://www.fingo.info/en/articles/_1.html。然而,我不确定这是否真的有效


共 (6) 个答案

  1. # 1 楼答案

    如果您正在使用java服务器端脚本,并且也在使用struts 2,那么您可以参考这个关于使用令牌的链接

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

    当请求第一次与令牌一起提交时,应生成令牌并将其保持在会话中,在struts操作中,以线程名称作为令牌id运行线程,并在客户端再次提交相同请求时,运行客户端请求的逻辑,检查线程是否仍在运行(thread.getcurrentthread()。中断)如果仍在运行,则发送客户端重定向503

    请看struts 2code的ExecuteAndWaitInterceptor,其逻辑与令牌相结合将有助于快速点击

  2. # 2 楼答案

    解决在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"});
    

    还有一个过滤器,可以扫描用户会话中的这些特定属性,并输出消息。由于状态消息通常只显示一次,因此过滤器应在读取一次后删除属性

  3. # 3 楼答案

    是的,我认为你应该在发帖后重定向,API请求除外。如果不这样做,用户使用“后退”按钮时,你不仅要担心会收到重复的帖子,而且当用户尝试使用“后退”按钮时,浏览器还会给用户提供恼人的对话框

    回应。sendRedirect在实践中是有效的,但从技术上讲,这是为此目的发送错误的HTTP响应代码。sendRedirect发送302,但将POST转换为GET的正确代码是303。(不过,大多数浏览器在回复帖子时会把302当成303)

    通常,您希望重定向将用户发送到任何显示其更改效果的视图。例如,如果他们编辑一个小部件,他们应该被重定向到该小部件的视图。如果他们删除了一个小部件,他们应该被重定向到该小部件存在时出现的视图(可能是小部件列表)

    有时,有一条状态消息可以进一步让人们了解某个动作发生的事实,这很好。一种简单的方法是在视图中设置一个公共参数,设置该参数后,将显示一条操作完成消息。例如:

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

    这里的“msg”参数包含消息“Widget modified”。这种方法的一个缺点是,恶意网站可能会向用户发送令人困惑/误导的消息。例如:

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

    如果你真的担心这个问题,你可以把消息的过期签名作为附加参数。如果签名无效或已过期,请不要显示该消息

  4. # 4 楼答案

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

    有些人发现“禁用所有备份,刷新此关键页面上的事件”更好; 我不确定这是好是坏

    但是您的寻址解决方案“垂直响应缓存””听起来不错

  5. # 5 楼答案

    这有点不明显,但:

    • 在用户会话中创建键控对象
    • 该值是结果的请求+java未来
    • 使用客户端重定向立即返回
    • 在处理客户端重定向时,让一个工作线程生成答案

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

    另一种方法是让用户痛苦地意识到数据库需要多长时间

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

    密钥很容易受到攻击,因为它是客户端响应的一部分,所以

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

    这种方法要求任何黑客都知道会话id和随机密钥

    这种方法似乎有些过分,但重定向强化机制可用于密码重置等情况

  6. # 6 楼答案

    我的一个想法是在提交后的表单中嵌入一个唯一的ID(可能是一个随机字符串)作为隐藏的表单字段。ID字符串可以作为“事务ID”放入数据库中。现在,当您要更新数据库时,首先检查是否存在具有提交的事务ID的现有记录,如果存在,则假定它是重复的,并且不更改数据库

    当然,正如我所说,这只是一个想法。我不知道实际使用的是什么方法。(我怀疑很多不那么关键的网站只是忽视了这个问题,希望他们的用户会聪明……如果我看到过的话,这是一个失败的提议;-)

    编辑:正如评论中指出的,在数据库中存储事务ID可能会占用大量空间,但如果这是一个问题,您可以将过去5分钟/1小时/1天/任何时间内处理的所有事务ID保留在内存缓存中。除非你遇到一个坚定的黑客