Ran*_*ang 6 ajax j-security-check jsf-2 viewexpiredexception
我有一个不受保护的JSF页面j_security_check.我执行以下步骤:
Firebug显示a ViewExpiredException正如预期的那样被提升.
帖子:
Run Code Online (Sandbox Code Playgroud)javax.faces.ViewState=8887124636062606698:-1513851009188353364响应:
Run Code Online (Sandbox Code Playgroud)<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不再引发.相反,响应只是一种新的视图状态.
帖子:
Run Code Online (Sandbox Code Playgroud)javax.faces.ViewState=-4873187770744721574:8069938124611303615响应:
Run Code Online (Sandbox Code Playgroud)<partial-response> <changes> <update id="javax.faces.ViewState">234065619769382809:-4498953143834600826</update> </changes> </partial-response>
有人可以帮我解决这个问题吗?我希望它引发异常,以便我可以处理该异常并显示错误页面.现在它只是响应一个新的ViewState,我的页面卡住了没有任何视觉反馈.
Bal*_*usC 10
我能够重现你的问题.这里发生的是容器调用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);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
更新此解决方案是因为OmniFaces 1.2已内置于OmniPartialViewContext.因此,如果您恰好使用OmniFaces,那么这个问题就完全透明地解决了,您不需要PhaseListener为此定制.
| 归档时间: |
|
| 查看次数: |
8051 次 |
| 最近记录: |