j_security_check not redirecting to welcome page - successful login event listener?

Oversteer picture Oversteer · May 10, 2012 · Viewed 7.4k times · Source

For ages I've been puzzled about why after login I sometimes don't directed to the application welcome page. I've finally figured it out (years after everyone else):

  • I login successfully via j_security_check and go to the welcome page

  • wait for session timeout

  • click on h:link which sends a GET request

  • because it's a GET and not a POST my custom ViewExpiredException
    handler doesn't kick in

  • container security redirects to the login page because the session
    has timed out. Because of the session timeout+container security the get request (from h:link) isn't seen by the application, in either a phase listener or filter.

  • I successfully login again

  • j_security_check redirects me to the page which triggered the
    authentication, in this case the target of the GET request.

The last bit I'd not understood, I assumed it would always go to the welcome page.

My problem is that my current design requires that after login I always show the welcome page. The welcome page has a preRenderView event which sets up some context information in a session scoped bean after login and increments a few counters etc...

This context information is required by backing bean code for other pages, and presently if I don't go through the welcome page first there'll be an exception.

In terms of fixing it I've looked at the following options:

  1. Ideally there'd be an @PostLogin method that could be called, which would cleanly solve all my problems. I use JSF (Mojarra) with Myfaces CODI but I don't see anything which does what I want.

  2. I could add some more code to my filter, but I need to persist some data (i.e. login count), it doesn't look like a nice option. Maybe I'm wrong.

  3. I make all the preRenderView methods of potential targets of j_security_check (pages called with GET) handle the case where they are called directly from j_seecurity_check. I can see this being what I have to do but it seems like a lot of hassle.

  4. Write a Server Authentication Module for glassfish to override j_security_check behavior.

How is this normally handled? I've started hitting this problem after moving to GETs for simple navigation cases after years of abusing POSTs, and the custom exception handler doesn't work. If anyone has any guidance on this issue I'd appreciate it, at least I know what's going on now. Hopefully I've missed something obvious!

Thanks O/S

Answer

BalusC picture BalusC · May 10, 2012

Ideally there'd be an @PostLogin method that could be called, which would cleanly solve all my problems. I use JSF (Mojarra) with Myfaces CODI but I don't see anything which does what I want.

There is indeed no such thing.


I could add some more code to my filter, but I need to persist some data (i.e. login count), it doesn't look like a nice option. Maybe I'm wrong.

That would indeed be the "easiest" way. Basically:

UserPrincipal user = request.getUserPrincipal();
HttpSession session = request.getSession();

if (user != null && session.getAttribute("user") == null) {
    session.setAttribute("user", user);

    // First-time login. You can do your intercepting thing here.
    response.sendRedirect(request.getContextPath() + "/welcome.xhtml");
}

I make all the preRenderView methods of potential targets of j_security_check (pages called with GET) handle the case where they are called directly from j_seecurity_check. I can see this being what I have to do but it seems like a lot of hassle.

That's not DRY.


Write a Server Authentication Module for glassfish to override j_security_check behavior.

Can't answer that as I've never done that.