Slash Boxes
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Ovid (2709)

  (email not shown publicly)
AOL IM: ovidperl (Add Buddy, Send Message)

Stuff with the Perl Foundation. A couple of patches in the Perl core. A few CPAN modules. That about sums it up.

Journal of Ovid (2709)

Wednesday August 19, 2009
04:01 PM

Handling login/logout correctly

[ #39494 ]

One thing frustrating about many Web sites is that login and logout often return you to the front page or keep you on the login or logout page. I hate that. You want to remain where you instead of navigating back to that. I've solved that with my Web app with Catalyst::Plugin::Session. It has a nifty 'flash' method. This is like the stash, except it's persistent across one request. Thus, in my Escape::Controller::Root 'auto' method, the method called before the others, I have this:

# 'none' is from Perl6::Junction
if ( $c->req->path eq none(qw/login logout/) ) {
    $c->flash->{path} = $c->req->uri->as_string;

With that, if you're not logging in or logging out, the flash path is the URI of where you were last at. My login/logout controllers automatically redirect you to the flashed path, thus keeping you where you were.

$c->response->redirect( $c->flash->{path} || $c->uri_for('/') );

The only tricky bit is that flash only keeps flash info which has changed since the last request. The keep_flash line keeps the path across multiple request.

I use the full URI in case someone is on a page like /country/?starts_with=m. My opinion is that every page on a Web site should respond sensibly to a GET request. If you hold to that, the above strategy seems sensible. Better strategies welcome :)

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
More | Login | Reply
Loading... please wait.
  • I'd just check $c->action (or $c->action->reverse) instead of the path, in case you reconfigure it one day to another path. The rest is very nice :)

    Ordinary morality is for ordinary people. -- Aleister Crowley
  • personal I do something like in sub end

    if ( $c->res->location ) {
    if ( $c->res->location eq '/login' ) {
    $c->flash->{path} = $c->req->uri->as_string;

    so that you don't need write session every request.
  • Just have the logout action accept a returnto query parameter, and stick the value of $c->req->uri into that when you emit the logout link. Much simpler; the server doesn’t have to do any bookkeeping, no DB accesses, nothing.

    Also, flash is bad anyway – subject to race conditions. It will restore the flashed variables into the session for whichever request happens to come in with the right session cookie, even if that request was made by a different tab/browser window/computer/scraper threa

    • I usually do something similar if I want to go to some other page after login/logout, but you don't need to prepopulate the login/logout links just use the REFERER header.

      • The referer is rather unreliable and can be, and is often, changed by the browser or a proxy.

        Ordinary morality is for ordinary people. -- Aleister Crowley
    • Agreed.  In any event, flash-based solutions are unlikely to win you friends who are truly security conscious when there are static methods that have worked forever that still work.  (And, for that matter, shockwave, java, or javascript solutions will also not motivate friends in the above mentioned crowd.)

      Passing the information as form values is especially a good idea because it then makes passing other form values a no brainer.  And when you do that, the login form no longer causes your us

      • Err, “flash” in this case does not refer to Macromedia Flash, rather, to a particular feature of the session plugin.

        • Sigh.  That's what happens when I try to comment on things while trying to catch up on my reading.  If it had been using Macromedia Flash, then it wouldn't be storing the data server-side.

          However, I do think my point still stands of this mentality tends to drops post form data.  It doesn't have to - one could store that in session data also, but it's considerably easier and less problematic to simply use forms, as indicated for the more general case in your original response.

  • It seems like you got what flash and stash are backwards, from the docs in the Session plugin. You say flash lasts for one request. This is what the doc for it says:

    "Think of it as a stash that lasts for longer than one request, letting you redirect instead of forward."

    Am I misunderstanding?

    • The stash lasts for the duration of a single request.

      The flash persists after the request and becomes part of the stash in the next request – but only once (unless you persist the data again).

      The terminology is kinda confusing, I guess.

      • Actually, it's not quite "persist the data again". Flash is only preserved if the data changes. Thus, if you need to preserve the same data across multiple requests, you need to use the keep_flash() method.