代码之家  ›  专栏  ›  技术社区  ›  Stephan

会话失效后的ViewExpiredException

  •  0
  • Stephan  · 技术社区  · 7 年前

    我得到了一个使用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相同。当异常发生时,服务器上的会话将被销毁并创建一个新的会话。

    0 回复  |  直到 7 年前