gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 17:38:26 24 4
gpt4 key购买 nike

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

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

Firebug 显示按预期引发了 ViewExpiredException

Post:

javax.faces.ViewState=8887124636062606698:-1513851009188353364

Response:

<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 不再引发。相反,响应只是一个新的 View 状态。

Post:

javax.faces.ViewState=-4873187770744721574:8069938124611303615

Response:

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

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

最佳答案

我能够重现您的问题。这里发生的情况是,容器按照安全约束中的指定调用 RequestDispatcher#forward() 到登录页面。然而,如果登录页面本身也是一个 JSF 页面,那么在转发的请求上也会调用 FacesServlet 。由于请求是转发,这将简单地在转发的资源(登录页面)上创建一个新 View 。但是,由于它是一个 ajax 请求,并且没有渲染信息(整个 POST 请求在安全检查期间基本上被丢弃),因此只会返回 View 状态。

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

不幸的是,它正在“按设计”工作。我怀疑 JSF 规范对 ajax 请求的安全约束检查存在一些监督。毕竟原因是可以理解的,而且幸运的是很容易解决。只是,您实际上不想在此处显示错误页面,而只想显示整个登录页面,就像在非 ajax 请求期间发生的情况一样。您只需检查当前请求是否是 ajax 请求并已转发到登录页面,然后您需要发送一个特殊的“重定向”ajax 响应,以便更改整个 View 。

您可以使用 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,那么这个问题就是 fully transparently已解决,您不需要为此自定义 PhaseListener

关于ajax - 如果 JSF 页面受 j_security_check 保护,则 ajax 请求不会引发 ViewExpiredException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61005524/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com