in reply to Catalyst Redirect Hints?

This can be semi-trivial in Cat. There are two ways to do it. The first, easiest, is debatably bad REST style (the content under any restricted URI becomes fluid; it's a login form or the real content) but the second can be tricky and has no "standard" implementation.

  1. Forward to login action under the requested URI until user is authenticated. Once authenticated, the requested URI never changed so it's trivial to redirect to the same resource.
  2. Capture the request info, put it in the session via flash or cache or session, redirect to login, keep the info there via flash, cache, or session and use it to send the user where they tried to start once they authenticate. This is trickier because you probably have to take into account request->referer existing or not and if its base equals that of the app's otherwise you could redirect an authenticated user off-site.

I recommend #1. Pseudo-code:

sub what_i_want : Local { $c->detach("login") unless $c->user_exists... roles... etc... do_interesting_restricted_stuff() } sub login : Local { if ( authenticated... ) { my $destination = $c->request->path eq 'login' ? $c->uri_for("/") : $c->uri_for( "/" . $c->request->path +); $c->response->redirect($destination); $c->detach(); } }

So, the user requests http://myapp/what_i_want but is presented with the login page since they aren't authenticated. The login posts to that same path, "what_i_want," until they are authenticated. Then just redirect to the requested path as long as it wasn't "login" to start with, that would be silly. Send them home -- "/" -- if they requested login to start the login process.

I know that can be a bit boggling at first but it's actually pretty straightforward once you get the right perspective on it. There is more of this in a few of the docs, sorry, no links right now. Let me (us) know if you get stuck on it.

Replies are listed 'Best First'.
Re^2: Catalyst Redirect Hints?
by holli (Abbot) on Mar 26, 2009 at 04:10 UTC
    If you put that in a auto function you don't even need to call it from the controller action. At my current project I am using this base controller for the protected area.
    package XXXXX::SecureBaseController; use strict; use warnings; use parent 'Catalyst::Controller'; sub auto: Private { my ( $self, $c ) = @_; # ungültiges User-Objekt in der Session unless ( $c->session->{user} ) { # Umleitung zum Login $c->response->redirect('/login/'.$c->request->path); return; } return 1; } 1;


    holli

    When you're up to your ass in alligators, it's difficult to remember that your original purpose was to drain the swamp.

      Nice approach++. I also generally do this stuff in auto() as well but not that way. I may adopt that myself. It's quite direct.

      Update: Oh, but I would change part of it.

      $c->response->redirect('/login/'.$c->request->path);

      Should be-

      $c->response->redirect($c->uri_for('/login', $c->request->path));

      Redirects are supposed to be absolute URIs (per the HTTP spec) and even though most stuff accommodates the relative ones there is at least one real world bug: I've seen them do freaky stuff in mod_perl; internally redispatching to an unrelated part of the app. That was a drag to track down.