在 JSF 2 的 AJAX 请求中重定向 ViewExpiredException
Redirect on ViewExpiredException in AJAX request in JSF 2
当我的会话在我的 Java EE 7、JSF 网络应用程序中过期时。
我在 ajax 个请求中收到 ViewExpiredException。
我想重定向到一个向用户显示会话已过期的页面。
我尝试浏览 google 和 Whosebug 寻找解决方案,但我没有任何运气让它按照我想要的方式工作。
更新:
我尝试了 posted @ Session timeout and ViewExpiredException handling on JSF/PrimeFaces ajax request
的解决方案
当我使用 login_submit 按钮时,它确实在我的登录页面上起作用。
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:h="http://xmlns.jcp.org/jsf/html"
template="./../templates/login_template.xhtml">
<ui:define name="title">
<h:outputText value="#{bundle.login_title}"/>
</ui:define>
<ui:define name="content">
<h:outputText escape="false" value="#{bundle.login_message}"/>
<h:form>
<h:panelGrid columns="2" cellpadding="5">
<h:outputLabel for="username" value="#{bundle.login_username}"/>
<p:inputText id="username" type="text" value="#{authBean.username}" label="username"/>
<h:outputLabel for="password" value="#{bundle.login_password}"/>
<p:inputText id="password" type="password" value="#{authBean.password}" label="password"/>
<h:outputText value="#{bundle.login_invalid_password}" rendered="#{!authBean.validPassword and authBean.validUsername}"/>
<h:outputText value="#{bundle.login_invalid_username}" rendered="#{!authBean.validUsername}"/>
<p:commandButton value="#{bundle.login_submit}" action="#{authBean.doLogin}"/>
</h:panelGrid>
</h:form>
</ui:define>
</ui:composition>
但它不适用于安全页面上的 xhtml 页面中的此 JSF,登录页面是 public 页面。例如,以下 xhtml 位于安全页面上:
<p:commandButton styleClass="button #{chartBean.isViewButtonActive('MONTH')}" update="dataChart dataTable @form" value="#{bundle.performance_year}" action="#{chartBean.changeModel('MONTH')}" />
这是一个 AJAX post 请求,但它被我的@WebFilter 捕获了。 (它也发生在 Primefaces 的 selectOneMenu 中)这个过滤器检查用户是否登录,如果没有,它会将他们重定向到登录页面。但是出于某种原因,我上面给出的示例按钮也被@WebFilter 捕获,并且 ajax 请求作为@WebFilter 中指定的响应重定向。它不会被 ExceptionHandler 捕获。 @WebFilter 仅适用于安全页面,见下文。
@WebFilter(
filterName = "AuthorizationFilter",
urlPatterns = {"/secure/*"},
dispatcherTypes = {DispatcherType.REQUEST, DispatcherType.FORWARD}
)
public class AuthorizationFilter implements Filter {
有谁知道如何解决这个问题。
我在 webfilter 中这样做,效果很好:
// Check if user logged in, if not redirect to login.xhtml
if (loginBean == null || !((LoginBean) loginBean).isLoggedIn()) {
boolean isAjax = "XMLHttpRequest".equals(req.getHeader("X-Requested-With"));
if (!isAjax) {
res.sendRedirect(req.getContextPath() + "/login.xhtml");
} else {
// Redirecting an ajax request has to be done in the following way:
// http://javaevangelist.blogspot.com/2013/01/jsf-2x-tip-of-day-ajax-redirection-from.html
String redirectURL = res.encodeRedirectURL(req.getContextPath() + "/login.xhtml");
StringBuilder sb = new StringBuilder();
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><partial-response><redirect url=\"").append(redirectURL).append("\"></redirect></partial-response>");
res.setCharacterEncoding("UTF-8");
res.setContentType("text/xml");
PrintWriter pw = response.getWriter();
pw.println(sb.toString());
pw.flush();
}
} else {
// Let chain of filters continue;
chain.doFilter(request, response);
}
当我的会话在我的 Java EE 7、JSF 网络应用程序中过期时。
我在 ajax 个请求中收到 ViewExpiredException。
我想重定向到一个向用户显示会话已过期的页面。
我尝试浏览 google 和 Whosebug 寻找解决方案,但我没有任何运气让它按照我想要的方式工作。
更新:
我尝试了 posted @ Session timeout and ViewExpiredException handling on JSF/PrimeFaces ajax request
的解决方案当我使用 login_submit 按钮时,它确实在我的登录页面上起作用。
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:h="http://xmlns.jcp.org/jsf/html"
template="./../templates/login_template.xhtml">
<ui:define name="title">
<h:outputText value="#{bundle.login_title}"/>
</ui:define>
<ui:define name="content">
<h:outputText escape="false" value="#{bundle.login_message}"/>
<h:form>
<h:panelGrid columns="2" cellpadding="5">
<h:outputLabel for="username" value="#{bundle.login_username}"/>
<p:inputText id="username" type="text" value="#{authBean.username}" label="username"/>
<h:outputLabel for="password" value="#{bundle.login_password}"/>
<p:inputText id="password" type="password" value="#{authBean.password}" label="password"/>
<h:outputText value="#{bundle.login_invalid_password}" rendered="#{!authBean.validPassword and authBean.validUsername}"/>
<h:outputText value="#{bundle.login_invalid_username}" rendered="#{!authBean.validUsername}"/>
<p:commandButton value="#{bundle.login_submit}" action="#{authBean.doLogin}"/>
</h:panelGrid>
</h:form>
</ui:define>
</ui:composition>
但它不适用于安全页面上的 xhtml 页面中的此 JSF,登录页面是 public 页面。例如,以下 xhtml 位于安全页面上:
<p:commandButton styleClass="button #{chartBean.isViewButtonActive('MONTH')}" update="dataChart dataTable @form" value="#{bundle.performance_year}" action="#{chartBean.changeModel('MONTH')}" />
这是一个 AJAX post 请求,但它被我的@WebFilter 捕获了。 (它也发生在 Primefaces 的 selectOneMenu 中)这个过滤器检查用户是否登录,如果没有,它会将他们重定向到登录页面。但是出于某种原因,我上面给出的示例按钮也被@WebFilter 捕获,并且 ajax 请求作为@WebFilter 中指定的响应重定向。它不会被 ExceptionHandler 捕获。 @WebFilter 仅适用于安全页面,见下文。
@WebFilter(
filterName = "AuthorizationFilter",
urlPatterns = {"/secure/*"},
dispatcherTypes = {DispatcherType.REQUEST, DispatcherType.FORWARD}
)
public class AuthorizationFilter implements Filter {
有谁知道如何解决这个问题。
我在 webfilter 中这样做,效果很好:
// Check if user logged in, if not redirect to login.xhtml
if (loginBean == null || !((LoginBean) loginBean).isLoggedIn()) {
boolean isAjax = "XMLHttpRequest".equals(req.getHeader("X-Requested-With"));
if (!isAjax) {
res.sendRedirect(req.getContextPath() + "/login.xhtml");
} else {
// Redirecting an ajax request has to be done in the following way:
// http://javaevangelist.blogspot.com/2013/01/jsf-2x-tip-of-day-ajax-redirection-from.html
String redirectURL = res.encodeRedirectURL(req.getContextPath() + "/login.xhtml");
StringBuilder sb = new StringBuilder();
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><partial-response><redirect url=\"").append(redirectURL).append("\"></redirect></partial-response>");
res.setCharacterEncoding("UTF-8");
res.setContentType("text/xml");
PrintWriter pw = response.getWriter();
pw.println(sb.toString());
pw.flush();
}
} else {
// Let chain of filters continue;
chain.doFilter(request, response);
}