我得到了一个使用primefaces6.0/jsf2.2的应用程序,其中我有以下场景。
public void login() throws IOException {
//.... Authentication mechanism here
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext externalContext = context.getExternalContext();
HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
externalContext.redirect(new StringBuilder(externalContext.getRequestContextPath())
.append("/homepage.jsf").toString());
return;
}
在同一个选项卡中,他从应用程序注销,然后被自动重定向到登录页面。
public String logout() {
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
externalContext.invalidateSession();
return "/login/login.jsf?faces-redirect=true";
}
注意
:当登录/注销实现在@SessionScoped处理程序中时,用于其操作/重定向的应用程序的其余部分是@ViewScoped。
<p:menuitem value="" url="/mypage.jsf?faces-redirect=true" />
此时,应用程序将通过javax.faces.application应用程序.ViewExpiredException:无法还原视图。stackoverflow中的mumerous posts描述了这种行为,其中一个在会话失效后给出了关于这种行为的详细信息(
javax.faces.application.ViewExpiredException: View could not be restored
)
我知道这并不是很相关,在jsf2.2上,它默认设置为false,仍然尝试了一下。
<context-param>
<param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<description></description>
<param-name>com.sun.faces.numberOfViewsInSession</param-name>
<param-value>15</param-value>
</context-param>
<context-param>
<description></description>
<param-name>com.sun.faces.numberOfLogicalViews</param-name>
<param-value>15</param-value>
</context-param>
此外,我还创建了一个过滤器来避免缓存,这里也提到过
Prevent user from seeing previously visited secured page after logout
@WebFilter(servletNames = { "facesServlet" })
public class LoginFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP
res.setHeader("Pragma", "no-cache"); // HTTP 1.0.
res.setDateHeader("Expires", 0); // Proxies.
chain.doFilter(request, response);
return;
}
}
我是一个摆设的器皿
javax.faces.STATE_保存方法
到
此外,我还创建了一个异常处理程序来处理Viewexpireexception并将用户重定向到特定的页面。当然,这只是为了处理这种情况,而不是解决问题。
更新1
我试图使用ajax设置为false的commandLink来重定向“我的网页.jsf“以防万一这是一个问题,但有完全相同的例外
<h:commandLink action="/mypagejsf?faces-redirect=true" ajax="false" value="My Link" />
更新2
在第一次登录并分析登录页面中的请求头之后,我注意到以下几点:
1) 浏览器上的sessionID与服务器上的sessionID匹配
2) Referer属性显示以下url
http://..../mypage.jsf?faces-redirect=true
. 这是我尝试访问时收到异常的页面。
更新3
我还注意到,当我试图访问我的网页.jsf在第二次登录之后(在异常发生之前),我的客户机请求(如果我没弄错的话)与服务器上同样存在的sessionId相同。当异常发生时,服务器上的会话将被销毁并创建一个新的会话。