【问题标题】:How to check for a valid session in JSF application?如何检查 JSF 应用程序中的有效会话?
【发布时间】:2019-01-16 02:15:17
【问题描述】:

在我解释情况之前,我先说我正在处理的应用程序是旧的、过时的、需要重写等,但我工作的公司不在乎,只是在寻找快速绷带解决这个问题。另外,我只是他们给这个应用程序的一个随机的家伙,尽管他们对这一切几乎一无所知,但他们不知何故认为我是主题专家。

我有一个 .xhtml 页面,用户可以访问该页面来支付账单。我们使用 SiteMinder 来控制对应用程序的访问,并通过它为应用程序设置了两个小时的不活动超时限制。但是,我们最近从第三方供应商那里实施了一些使用模式窗口的新支付功能。如果用户在这个 .xhtml 页面上停留一小时五十九分钟,调用模态窗口(通过单击按钮),然后去完成模态中的各种操作,那么当他们完成时,第三方供应商会考虑动作成功(因为他们不知道我们的超时),但我们没有收到他们的任何响应,因为会话已经超时。这是一个问题,因为用户可以安排未来的付款,如果我们没有从供应商那里得到响应,我们的数据库中就没有任何东西可以存储,我们最终会使用它来触发预定的付款。

当用户单击调用第三方模态窗口时,如何确定用户的会话是否仍然有效?以下是其中一个按钮的外观:

<p:commandButton id="makePaymentButton" 
    value="Make Payment" onclick="makePayment(/*args*/);"
</p:commandButton>

基本上,我想先检查并确保用户的会话仍然有效,而不是立即调用模式窗口。由于单击此按钮时没有页面导航或服务器交互,因此模式只是呈现用户的会话是否已过期。

【问题讨论】:

  • 伊恩,当我读到你的第一段时,我笑出了声。我完全知道你在说什么......
  • "当用户点击调用第三方模态窗口时,如何判断用户的会话是否仍然有效?" - 但在您自己的示例中,此时会话仍然有效(1h 59m),所以这无济于事。我认为问题是在用户填写第 3 方对话框时会话变得无效。
  • @VsevolodGolovanov - 今天早上我在闹钟响之前躺在床上时确实想到了这个。你是对的 - 这不能完全解决我的问题。我只会确保会话在用户调用模式时有效。所以现在我想知道如何避免他们的会话死亡。

标签: ajax jsf primefaces


【解决方案1】:

如果您使用标准渲染套件,请使用:

<h:commandButton id="makePaymentButton"
                 value="Make Payment" 
                 actionListener="your action listener which may return an exception if the session control fails">
    <f:ajax onevent="makePayment(/*args*/)" />
</h:commandButton>

如果您使用 Primefaces,请使用“oncomplete”、“onsuccess”:

<p:commandButton id="makePaymentButton" 
                 value="Make Payment" 
                 actionListener="your action listener which may return an exception if the session control fails" 
                 onsuccess="makePayment(/*args*/)" />

然后,在 actionListener 中你可以得到会话:

HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);

注意:会话引用可能为空,然后检查您需要什么。

不要忘记放置 &lt;f:view transient="true"&gt; ... &lt;/f:view&gt; 以禁用自动创建 JSESSIONID。

【讨论】:

  • 好的创意建议!
  • ajax 提交可能会自己创建一个新会话,这可能是 OP 最终想要的,但不是他所要求的。此外,如果这意味着 onsuccess 被触发取决于 actionListener 抛出异常,那么这是错误的。
  • getSession(false) 如果会话不存在,则不会创建会话。关于onsuccess的其他commenr,我稍后会检查,但我过去是这样做的。
  • 也许它正在检查 arg.validationFailed ...我将不得不检查我的旧项目。
  • getSession(false) 无关紧要 - 会话将在此之前由 JSF impl 创建。
【解决方案2】:

要知道会话是否仍然有效,您需要询问服务器。但是您必须小心,以免您的“询问”请求本身不会自动创建新会话。最可靠的方法是完全放弃 JSF 并创建一个简单的 Servlet。

public class CheckSessionServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/plain");

        HttpSession session = request.getSession(false);
        if (session == null) {
            // no session, let's respond 404
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
        } else {
            // session exists - return a succesful status
            response.setStatus(HttpServletResponse.SC_NO_CONTENT);
        }
    }

}

使用 JS 向该 servlet 发出 AJAX POST 请求,然后根据请求结果进行操作。

为了防止用户在填写第 3 方对话框时会话超时,您可能需要触摸会话以延长其超时时间:

        } else {
            // session exists - bump timeout & return a succesful status
            session.setAttribute("someUnusedAttribute", 123);
            response.setStatus(HttpServletResponse.SC_NO_CONTENT);
        }

如果会话过期,那么您可以刷新页面(使用 JS)以允许用户重新开始。或者向用户显示一条简单的消息,说明会话已经结束,他需要重新开始。

您可以在不触及遗留 JSF 内容的情况下完成所有这些操作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-26
    • 1970-01-01
    • 2012-01-11
    • 2012-10-02
    • 2010-11-23
    • 2012-06-08
    • 2020-10-31
    • 2014-01-14
    相关资源
    最近更新 更多