[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:
http://search.cpan.org/dist/Dancer/lib/Dancer/Cookbook.pod#Sessions_and_logging_in
[...]
> 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:
http://search.cpan.org/dist/Dancer/lib/Dancer/Cookbook.pod#Sessions_and_logging_in
but change the before filter to, e.g.:
before sub {
if (! session('user') && request->path_info =~ m{/admin/}) {
var requested_path => request->path_info;
request->path_info('/login');
}
};
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?
Cheers
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