【问题标题】:Best strategy to handle page navigation in JSP在 JSP 中处理页面导航的最佳策略
【发布时间】:2011-06-15 05:04:17
【问题描述】:

我正在探索 JSP 来实现动态网页。要解决的一个问题是页面之间的导航。用户可以在他们的浏览器中来回切换。

这必须处理。如果有人注销(例如),我们不希望其他人通过单击“返回”来检索会话或数据。另一个例子是我们不想重新提交表单两次。

我正在寻找解决页面导航问题的提示和建议。我想创建一个必须处理的问题列表 + 可能的解决方案:

问题:

  • 确保无法通过返回/前进点击来检索/劫持会话
  • 确保表单没有提交两次
  • 确保用户无法使用 cookie 或 URL 数据或隐藏字段来破坏控制流和安全性

解决方案:

  • 实现一组已访问页面
  • 当一个页面被调用时,注册它的显示时刻以区分新请求和“返回”
  • 控制当前会话

P.S.:我看过这个question,但没有真正的答案。

【问题讨论】:

  • 动态网页是指通过ajax加载内容吗??
  • @jimy 不,不是。在 JSP 中,您可以将 Java 与 HTML 混合使用。当您显示 JSP 页面时,java 部分可以决定在每次调用它时显示不同的内容。问题是用户可以向前和向后导航。
  • 您是否故意只使用 JSP 页面?您是否知道,即使您可以在 JSP 页面中编写 Java 代码(= scriptlet),但通常不鼓励这样做,因为 JSP 主要用作“哑”视图组件,它只显示从后端的实际业务逻辑传递给它的任何内容(即 servlet、MVC 控制器等)。
  • @deltaforce2 我有很多可操作的 Java 代码,我想将它们用于 Web 应用程序。我发现 JSP 很有吸引力,因为它混合了 HTML 和 Java。现在,也许我需要花时间阅读 Struts 等框架。

标签: java jsp navigation


【解决方案1】:

确保无法通过返回/前进点击来检索/劫持会话

这些页面中只有disable browser cache。另见Prevent user from seeing previously visited secured page after logout


确保表单没有提交两次

生成一个长的、唯一的、无法猜测的字符串,将其存储在两个会话中..

String token = UUID.randomUUID().toString();
((Set<String>) session.getAttribute("tokens")).add(token);
request.setAttribute("token", token);
request.getRequestDispatcher("/WEB-INF/page.jsp").forward(request, response);

.. 并作为表单的隐藏输入字段。

<input type="hidden" name="token" value="${token}" />

提交后,比较并删除会话中的密钥。如果它在会话中,则继续提交。

if (((Set<String>) session.getAttribute("tokens")).remove(request.getParameter("token")) {
    // Valid token. Proceed with submit.
} else {
    // Invalid token. Possible double submit.
}

确保用户不能使用 cookie 或 URL 数据或隐藏字段来破坏控制流和安全

自己编写健壮的代码或使用现有的健壮的 MVC 框架,如 JSF2、Spring-MVC、Struts2 等。


解决方案:

  • 实现一个已访问页面的堆栈
  • 当一个页面被调用时,注册它显示的时间来区分新的请求和“返回”
  • 控制当前会话

麻烦。

【讨论】:

  • 只是关于隐藏字段的一个小问题,现在即使我在提交之前检查源代码我仍然可以看到令牌是什么?在提交等时,这意味着您需要提前知道会有哪些令牌,如果您在会话中有它们,为什么不使用会话而不是隐藏字段?
  • @Rafael:你真的可以看到它。我不明白这是怎么回事。至于独占使用会话,您将如何使用会话来防止重复提交?在每次提交时使其无效还是什么?这很麻烦。另外,您如何考虑用户在同一会话中打开多个窗口/选项卡的可能性?
  • 我的意思是,如果有人能够看到隐藏的领域,他仍然可以打破事物的流动。并且要防止重复提交,这一切都取决于它是哪种网站。如果它是一个销售网站,让他们支付双倍还不错;)
  • @Rafael:可能发生的最糟糕的事情是由于令牌无效而无法提交表单。我不确定这有多糟糕,因为是最终用户本身造成了这种情况。
【解决方案2】:

为了防止重复提交,我将使用一个使用 HttpSession 的示例 Apache Struts 1。

Struts 所做的是生成一个随机令牌,该令牌存储在会话中并添加到表示层 (JSP) 的表单页面中。当用户提交表单时,它会从会话中检查表单给出的令牌是否与会话中的会话完全相同。如果为真,则处理请求,否则为双重提交。

例子:

public class AuthenticationAction extends Action {

    public void displayLogout(ActionMapping mapping, ActionForm form,
                        HttpServletRequest request, HttpServletResponse response) throws Exception {

        saveToken(request);
        return mapping.findForward("displayLogout");
    }

    public ActionForward doLogout(ActionMapping mapping, ActionForm form,
                        HttpServletRequest request, HttpServletResponse response) throws Exception {

        if (isValidToken(request)) {
            //It wasn't yet a double submission, delete token generated by Struts
            resetToken(request);
            //logout.
            ...
            //return back home
            return mapping.findForward("home");
        } else {
            //Double submission..
            throw new Exception("double submission");
        }
    }
}

找到更好的教程here

【讨论】:

【解决方案3】:

嗯,如果你愿意,你也可以使用 Spring Webflow 框架,但是使用 back 和 refresh 不提交表单两次可以通过定义控制器权限轻松解决。我认为使用 REST 也可以帮助解决一些问题。

隐藏字段操作是另一回事,因为始终可以在页面源中查看隐藏字段。如果可以查看该字段,则可以对其进行操作。

【讨论】:

  • 我认为 REST 是一种过度设计的技术...但对于其余的(坏双关语)我 +1...
【解决方案4】:

为避免重新发明轮子,使用现有框架似乎是最佳解决方案。 Struts 看起来是个不错的选择。简单介绍tutorial即可。

【讨论】:

  • Struts 2 是 Struts 的一个较新的框架。我从未使用过它,但请确保它有助于解决您的重复提交问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-13
  • 1970-01-01
  • 1970-01-01
  • 2016-09-29
  • 1970-01-01
相关资源
最近更新 更多