[Dancer-users] best practices: how to require a login for parts of the site...

David Precious davidp at preshweb.co.uk
Sat May 29 14:28:54 CEST 2010

On Saturday 29 May 2010 02:28:44 Daniel Pittman wrote:
> One of the requirements I am going to hit in the near future is that we
> will need to provide some public and some routes inside a single
> application.

A pretty common requirement :)
> When users hit anything under a specific path, basically, they need to have
> an already validated login, or else we need to send 'em off to get one. 
> The most basic "implement a login form" style thing pattern, nothing
> fancy.

There's an example of doing this in the Dancer Cookbook:


> My current model is to provide a plugin akin to this:
> That then gets used with a route like this:
> get '/example/:arg' => with_auth {
>     # normal handler here
> };

That looks quite useful - you might want to consider releasing that to CPAN :)

> I considered the approach of hooking all requests and performing my own URL
> matching to determine if they should require authentication, but that seems
> to require that I duplicate an awful lot of code from the Dancer route
> system.

Yes, if all the bits that should be protected aren't under a common prefix, 
then you would be duplicating some info, but otherwise, using a before handler 
to do it is easy...

> Oh.  I did consider this construction, but found it hard to get right,
> especially if I wanted to cover '/admin' as well as pages under it.
>     get r('/admin/.*') => sub {
>         session('user') or redirect '/login', 302;
>         pass;
>     };
>     get '/admin/example' => sub {
>         # ...should only be called *after* the first route calls 'pass'
>     };
> Is that just my messing up or something?

What you're trying to do there would be better handled with a before filter.

You could base it upon the example given in the cookbook:


but change the before filter to, e.g.:

    before sub {
        if (! session('user') && request->path_info =~ m{/admin/}) {
            var requested_path => request->path_info;

So, any request to a path starting with /admin/ gets sent to the /login route 
instead.  (It's basically what you had, but using a before filter rather than 
a route which has to pass).

Hope this helps a bit?


Dave P

David Precious <davidp at preshweb.co.uk>
http://blog.preshweb.co.uk/    www.preshweb.co.uk/twitter
www.preshweb.co.uk/linkedin    www.preshweb.co.uk/facebook
www.preshweb.co.uk/identica    www.lyricsbadger.co.uk

  "Programming is like sex. One mistake and you have to support 
  it for the rest of your life". (Michael Sinz)

More information about the Dancer-users mailing list