0

I got an application using Primefaces 6.0 / JSF 2.2 in which i have the following scenario.

A use logs in by interacting with a @SessionScoped bean in the application and is redirected to the homepage.jsf. After that, the user navigates to a page through a menuitem (mypage.jsf).

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;
}

From the same tab, he then logs out from the application and is autmaticaly redirected to the login page.

public String logout() {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    ExternalContext externalContext = facesContext.getExternalContext();
    externalContext.invalidateSession();
    return "/login/login.jsf?faces-redirect=true";
}

Note: While the login/logout implementation is within a @SessionScoped handler, the rest of the application for its actions/redirections are @ViewScoped.

The user logs in again in the application and tries to navigate through the same p:menu item on the same page he was before (mypage.jsf)

<p:menuitem value="" url="/mypage.jsf?faces-redirect=true" />

At this point the application throughs a javax.faces.application.ViewExpiredException: View could not be restored . This behavior is described in mumerous posts in stackoverflow, with one of them giving detailed information about this behavior after an invalidation of the session (javax.faces.application.ViewExpiredException: View could not be restored)

Things i tried: I know this is not that much relevant and that on JSF 2.2 it is set on false by default, still gave it a try.

<context-param>
    <param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name>
    <param-value>false</param-value>
</context-param>

Setting manually the number of views in session. Note that only 1 or 2 users work on the application but set it just in case.

<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>

In addition, i have created a filter to avoid caching as mentioned also here 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;
    }
}

I am a ware that setting javax.faces.STATE_SAVING_METHOD to client might solve my issue, but this is something i try to avoid.

In addition i have created an exception handler to handle a Viewexpireexception and redirect the user to a specific page. Of course this is just to handle such a situation and not solving the issue.

Update 1

I tried to use a commandLink with ajax set to false for the redirection on "mypage.jsf" just in case that was an issue but had exactly the same exception

<h:commandLink action="/mypagejsf?faces-redirect=true" ajax="false" value="My Link" />

Update 2 After loging out for the first time and analysing the request headers from the login page, i noticed following:

1) The sessionID on the browser matches with the one on the server

2) The Referer attribute shows to the following url http://..../mypage.jsf?faces-redirect=true . This is the page that i receive the exception when i try to access it.

Update 3 I also noticed, that when i try to access the mypage.jsf after a second login (before the exception occurs), my client requests (if i am not mistaken) with the same sessionId that exists also on the server. When the exception occurs, the session on the server is destroyed and a new session is created.

Stephan
  • 696
  • 15
  • 37
  • 1
    what does _"The user logs in again in the application and tries to navigate through a p:menu item on the same page he was before "_ mean, especially the **same** page? Does the user keep a page open? e.g. in another tab? – Kukeltje Dec 11 '18 at 15:34
  • I edit the question accordingly. By same page i mean the mypage.jsf he navigated on the first login. After the second login the user tries to navigate on the same page again (mypage.jsf) – Stephan Dec 12 '18 at 08:00
  • In which page is the ``? I don't think, a login-page has a menu? – Holger Dec 12 '18 at 08:11
  • Modified again. When the user performs a login (code snippet added), the user is automatically redirected to the homepage. There he has the option through the menu item to navigate to the page i refered. Please let me know if further information is required. Thank you – Stephan Dec 12 '18 at 08:30
  • Please have a look at the used urls in the browser. I had some problems with view expired exceptions because my pages were accessible with and without the context path and the session-cookie contained the context path. – Holger Dec 12 '18 at 09:01
  • 1
    @Holger what do you mean exactly ? To be for example at the login page and my browsers url to show the previous page ? I did not fully understand what information to look for. – Stephan Dec 12 '18 at 09:16
  • While deploying the project, you will be asked for a context-root or context-path. this path is normally contained in all urls. I.e. `http://localhost:8080/dvlp/main.xhtml` dvlp is the context-path. But in my configuration, the page is also accessible with `http://localhost:8080/main.xhtml`. If you do redirects programmatically, you may insert the context-path or miss it. In both forms, the page will be shown. So have a look, if the path in your urls is allways the same. – Holger Dec 12 '18 at 09:28
  • As seen in my programmatic redirection i include the context path ( externalContext.getRequestContextPath() ) . homepage.jsf is not accessible without the context patch (HTTP 404 Error) – Stephan Dec 12 '18 at 10:57

0 Answers0