2

I have the following problem with the timeouts in Spring Security with JSF:

I've customized the sessionmanagement filter so that the user is redirected to the invalidSessionUrl just if the requested page is secured (i.e. if it is allowed just for authenticated users). The custom code I put into the session management filter provided by Spring Security is:

if (invalidSessionUrl != null) {
     String pagSolicitada = UtilSpringSecurity.extraerPagina(request);
     if ( UtilSpringSecurity.paginaAutenticada(pagSolicitada ) ) {
          request.getSession();
          redirectStrategy.sendRedirect(request, response, invalidSessionUrl);
          return;
     }
     //the requested page doesn't require the user to be authenticated
     //so i just skip this filter and continue with the filter chain
     chain.doFilter(request, response);
     return;
}

The method "UtilSpringSecurity.extraerPagina(request)" returns the requested page this way:

public static String extraerPagina (HttpServletRequest request) {
     String uri = request.getRequestURI().toLowerCase();
     String cPath = request.getContextPath().toLowerCase();
     // uri = cPath + pagina
     int longCPath = cPath.length();
     String pagina = uri.substring(longCPath);
     return pagina;
}

And the method "UtilSpringSecurity.paginaAutenticada(pagSolicitada)" returns true if the the param is a page that requires the user to be authenticated (I do the check with IFs, considering the intercept-url elements of my xml security config file which have the attribute access="isAuthenticated()"):

public static boolean paginaAutenticada (String pagina) {

     if (pagina.startsWith("/faces/paginas/administracion/") || pagina.startsWith("/faces/paginas/barco/") ) {
          return true;
     }
     return false;
}

This solution works, but it has just one problem:

If I leave the browser staying idle at a page until the session timeout expires, and then I request the same page, then I get a "viewExpiredException". This is because the filter worked well, it bypassed the redirection to the invalidSessionUrl, but as the session expired anyway, then I get that exception trying to re-render the same page.

If I request any other unsecured page when the session timout has expired, it works well, it redirects correctly to the page and I don't get the viewExpiredException.

Anyone knows how to solve this?

Thank you in advance.

choquero70
  • 4,470
  • 2
  • 28
  • 48
  • `it bypassed the redirection to the invalidSessionUrl, but as the session expired anyway, then I get that exception trying to re-render the same page.` I do not understand what this means. Are you saying that when you rerender the invalidSessionUrl you get a ViewExpiredException? – maple_shaft Feb 22 '12 at 12:09
  • Why are you writing your own session management filter? Spring security gives you this functionality out of box. Just add the following to your Spring xml configuration ` ... ` – maple_shaft Feb 22 '12 at 12:14
  • Answer to your 1st comment: `it bypassed the redirection to the invalidSessionUrl, but as the session expired anyway, then I get that exception trying to re-render the same page`. I mean that I get the "viewExpiredException" when I re-render the unsecured page that the browser is showing when the timeout happens. This occurs because JSF can't build the view of the page, because the session has expired. Spring Security skips the session management filter because the page is not secured (this is ok), but then when JSF tries to re-render the page, it throws the exception. – choquero70 Feb 22 '12 at 21:48
  • Answer to your 2nd comment: Spring Security doesn't give the functionality I want out of the box. I want to skip the session management filter for requested pages that are not secured. The default filter doesn't implement this neither it is configurable via xml. That's why I write my own filter, which is the same as the default, but adding the check to see wether the requested page is secured or not. In case it is not secured, I skip the filter in order to not be redirected to the invalidSessionUrl. This works ok. – choquero70 Feb 22 '12 at 21:54

2 Answers2

3

Spring security should give you anonymous access to sets of pages for an un-authenticated user. Below is an excerpt of my XML configuration for how I achieved this.

<http auto-config="true" access-denied-page="/unauthorized.xhtml" >
    <intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
    <intercept-url pattern="/app/**" access="ROLE_USER,ROLE_ADMIN" />
    <intercept-url pattern="/*.xhtml" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    <form-login login-page="/login.xhtml" login-processing-url="/j_spring_security_check"
        authentication-success-handler-ref="authenticationSuccessBean"
        authentication-failure-handler-ref="authenticationFailureBean"  />
    <session-management invalid-session-url="/login.xhtml" >
    </session-management>
</http>

I essentially use intercept-url tags to claim that pages within certain relative contexts can only be accessed by the following roles. You can see that all pages at the web application default context are available to anonymous users. If the user is unauthorized to view the page then they will be redirected to access-denied-page.

The only catch is that your User bean has to implement the UserDetails interface and have a property that returns a role bean which implements the GrantedAuthority interface. Spring will look for a UserDetails to have a GrantedAuthority property to determine what the role is. If this user does not exist, is unauthenticated, or unknown then it will default to anonymous role.

maple_shaft
  • 10,435
  • 6
  • 46
  • 74
  • I know what you say, but that's not what I'm looking for. Refering to your scenario, any user (authenticated or not) will be redirected by the sesion-management-filter to the invali-session-url when session is timedout if they request a page that has the access property "IS_AUTHENTICATED_ANONYMOUSLY" (i.e. any page who match the pattern "/*.xhtml" and that is not in the admin or app directory). But what I want is not be redirected to the invalid-session-url in that case, just show the page I requested as if the session hadn't timedout (i.e. not apply the session-management-filter in that case) – choquero70 Feb 23 '12 at 21:22
0

Finally I solved it. It's a JSF issue, nothing to do with Spring Security.

I've overriden the restoreView method of jsf this way:

@Override
public UIViewRoot restoreView(FacesContext facesContext, String viewId) {
     UIViewRoot root = wrapped.restoreView(facesContext, viewId);
     if(root == null) {
          root = createView(facesContext, viewId);
     }
     return root;
}

Now the problem is that if the page had parameters, I lost them when I do the post to the recently created view, but that's another distinct issue (PRG pattern) dealing again with JSF.

choquero70
  • 4,470
  • 2
  • 28
  • 48