2013-02-19 78 views
1

我使用omnifaces FullAjaxExceptionHandler重定向时发生任何异常与ajax请求,在我的情况下捕获ViewExpiredException。重定向后的JSF Ajax(ViewRoot)更新

我会尽力解释我的情况:?

1)我有一个命令按钮(Ajax请求的index.xhtml页)无效的会话,并返回一个动作像这样“/登录面临重定向=真”。

2)在同一浏览器中打开index.xhtml两次。

3)在第一个的index.xhtml中单击按钮(会话是无效,并重定向到login.xhtml)

在这一点上您考虑我有一个自定义的PhaseListener来检查用户是否成功地记录,login.xhtml是向公众开放,但的index.xhtml仅限于授权用户,web.xml中的视图过期,403错误是:

<error-page> 
    <exception-type>javax.faces.application.ViewExpiredException</exception-type> 
    <location>/index.xhtml</location> 
</error-page> 
<error-page> 
    <error-code>403</error-code> 
    <location>/403.xhtml</location> 
</error-page> 

4)转到第二的index.xhtml(会话无效在这一刻),现在点击按钮启动异常。

FullAjaxExceptionHandler捕获ViewExpiredException并尝试呈现index.xhtml,但同时我的phaselistener正在检查用户是否被授权,如会话失效,用户未被授权,并且我的PhaseListener触发responseSendError(403) ,但没有显示403.xhtml,因为是ajax请求。

如何从我的PhaseListener发送403错误以显示403.xhtml? responseSendError取消了FullAjaxExceptionHandler的正常处理,此时此异常发生时不发生重定向。

此外,为了澄清视图何时到期,我需要重定向到index.xhtml,因为在生产中我使用CAS(中央身份验证服务)。

回答

1

具体问题实质上与FullAjaxExceptionHandler无关。不使用它时,你仍然会遇到完全相同的问题。这是不可能的Ajax请求使用responseSendError()至少2个原因:

  1. Ajax响应必须在订单状态200被成功处理。
  2. ajax响应必须表示有效的JSF ajax XML结构,而不是纯HTML页面。

PhaseListener里面,最好的选择是使用ExternalContext#redirect()

ExternalContext ec = context.getExternalContext(); 

if (context.getPartialViewContext().isAjaxRequest()) { 
    ec.redirect(ec.getRequestContextPath() + "/403.xhtml"); 
} else { 
    ec.responseSendError(403, "Unauthorized"); 
} 

诚然,这结束了在HTTP 200响应,但是这是迄今为止,当你要显示的全部错误页面在一个Ajax请求的情况下,你可以得到最好的。


无关的具体问题,如果ViewExpiredException被抛出了,那么原因是在几乎所有情况下,在会话过期。让异常的错误页面直接指向/login.xhtml而不是/index.xhtml会更有意义。或者,至少更多的用户友好,一些/expired.xhtml页面,其中有一个解释为什么最终用户最终在那里,他的选择,以及一些链接。

+0

在这种情况下,我需要读取web.xml以获取配置的错误页面。我会改变我的代码。谢谢Balus。 – Kab 2013-02-20 13:19:23