当前位置: 首页 > 面试题库 >

如果JSF页面受j_security_check保护,则不会在ajax请求上引发ViewExpiredException

聂琨
2023-03-14
问题内容

我有一个JSF页面,不受的保护j_security_check。我执行以下步骤:

  1. 在浏览器中打开JSF页面。
  2. 重新启动服务器。
  3. 单击JSF页面上的命令按钮以发起ajax调用。

Firebug ViewExpiredException如预期的那样显示了a 的增加。

发布:

javax.faces.ViewState=8887124636062606698:-1513851009188353364

响应:

>     <partial-response>
>     <error>
>     <error-name>class javax.faces.application.ViewExpiredException</error-
> name>
>     <error-message>viewId:/viewer.xhtml - View /viewer.xhtml could not be
> restored.</error-message>
>     </error>
>     </partial-response>

但是,一旦我将页面配置为受其保护j_security_check并执行上面列出的相同步骤,(对我而言)奇怪的ViewExpiredException是,该页面不再出现。相反,响应只是一个新的视图状态。

发布:

javax.faces.ViewState=-4873187770744721574:8069938124611303615

响应:

>     <partial-response>
>     <changes>
>     <update
> id="javax.faces.ViewState">234065619769382809:-4498953143834600826</update>
>     </changes>
>     </partial-response>

有人可以帮我解决这个问题吗?我希望它会引发异常,因此我可以处理该异常并显示错误页面。现在它只是以新的ViewState进行响应,我的页面被卡住了,而没有任何视觉反馈。


问题答案:

我能够重现您的问题。这里发生的是容器RequestDispatcher#forward()按照安全性约束中的指定调用登录页面。但是,如果登录页面本身也就是JSF页面,则FacesServlet还将在转发的请求上调用。由于请求是转发的,因此只会在转发的资源(登录页面)上创建一个新视图。但是,由于这是一个ajax请求,并且没有任何render信息(整个POST请求在安全检查转发过程中基本上被丢弃),因此仅返回视图状态。

请注意,如果登录页面不是JSF页面(例如JSP或纯HTML),那么ajax请求将返回该页面的整个HTML输出作为ajax响应,这是JSF
ajax无法解析的,并被解释为“空”响应。

不幸的是,它是“按设计的”方式工作的。我怀疑JSF规范中对ajax请求的安全性约束检查有一些疏忽。毕竟,原因是可以理解的,而且很容易解决。只是,您实际上并不希望在此处显示错误页面,而是仅显示整个登录页面,这与非ajax请求期间的情况完全相同。您只需要检查当前请求是否为ajax请求并将其转发到登录页面,则需要发送特殊的“重定向”
ajax响应,以便更改整个视图。

您可以通过以下方法实现此目的PhaseListener

    public class AjaxLoginListener implements PhaseListener {

        @Override
        public PhaseId getPhaseId() {
            return PhaseId.RESTORE_VIEW;
        }

        @Override
        public void beforePhase(PhaseEvent event) {
            // NOOP.
        }

        @Override
        public void afterPhase(PhaseEvent event) {
            FacesContext context = event.getFacesContext();
            HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
            String originalURL = (String) request.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI);
            String loginURL = request.getContextPath() + "/login.xhtml";

            if (context.getPartialViewContext().isAjaxRequest()
                && originalURL != null
                && loginURL.equals(request.getRequestURI()))
            {
                try {
                    context.getExternalContext().invalidateSession();
                    context.getExternalContext().redirect(originalURL);
                } catch (IOException e) {
                    throw new FacesException(e);
                }
            }
        }
    }

更新 此解决方案是因为OmniFaces
1.2
已内置到OmniPartialViewContext。因此,如果您碰巧已经使用过OmniFaces,则可以完全透明地解决此问题,并且不需要PhaseListener为此自定义。



 类似资料:
  • 问题内容: 想象一下下一个场景:用户想要注册到网页并填写表格。当他填写表格时,jQuery会通过正则表达式检查字段是否有效等。 将电子邮件作为用户注册后将使用的主键,需要使用Ajax来检查电子邮件字段,以使用户知道该电子邮件是否已注册。我想使用Ajax进行检查,以避免发送完整的表单并清空它,刷新页面等。 因此,当用户结束填写电子邮件字段时,Ajax请求将发送到服务器,类似于下一个链接: 当chec

  • 我正在使用ThinkTecture.IdentityModel nuget包为MVC Web应用程序中的WebAPI控制器启用CORS。目前,我只担心文章,但让我知道任何问题与其他动词。这在运行IIS Express服务器时有效。 在处理AppHarbor部署时,它不起作用。nginx似乎不会将选项请求传递给我的代码。还需要什么才能让它在Appharbor上运行? 选项$PATH HTTP/1.1

  • 问题内容: 我正在尝试将HttpServletRequest.login与基于表单的身份验证一起使用。 一切正常(容器会告诉您登录名/密码是否正确),除了在用户输入登录名之后,我不知道如何将用户重定向到他要求的受保护页面(重新显示登录表单)。怎么做? 在此先感谢您的帮助。 代码: web.xml: 页面loginwithlogin.xhtml 更新:没有Ajax,它将不起作用。 后备豆: 问题答案

  • 问题内容: 我在我的网站上做了一些非常基本的jQuery ajax的工作,并且遇到了很多麻烦。 以下是相关代码: 该页面是通过HTTPS加载的,但是XMLHttpRequests似乎是通过HTTP输出的。 我甚至尝试将URL更改为绝对URL(https://larsendt.com/jsontest/randomdata),它 仍然 将请求发送到我的站点的HTTP版本。 自然,由于请求将转到其他协

  • 问题内容: 但是当我使用AJAX调用提交时无法使用此功能 假设在一个primefaces对话框中,我正在使用AJAX发出发布请求,并且会话已经超时。我看到页面卡住了。 如何解决这种情况,以便在我使用AJAX发布时,可以将他重定向到我的视图过期页面,然后将他转发到登录页面,类似于上面的链接中的解决方案? JSF2 / Primefaces /玻璃鱼 问题答案: 默认情况下,ajax请求期间引发的异常

  • 我有一个带有按钮的搜索栏。当按钮被点击时,search_on_click功能运行。该函数应该检索URL的html并将其显示在页面上。 这是我目前掌握的代码。这些问题包括: > 我尝试过获取/请求,但问题大致相同 谢谢你抽出时间。