From: Yuval Kogman Date: Sun, 11 Dec 2005 13:32:23 +0000 (+0000) Subject: More docs - code examples X-Git-Tag: v0.05~8 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=5e91c0578638c6e1136db44a404c7023a285b2b0;p=catagits%2FCatalyst-Plugin-Authentication.git More docs - code examples --- diff --git a/lib/Catalyst/Plugin/Authentication.pm b/lib/Catalyst/Plugin/Authentication.pm index 877d85c..970e6d4 100644 --- a/lib/Catalyst/Plugin/Authentication.pm +++ b/lib/Catalyst/Plugin/Authentication.pm @@ -298,6 +298,154 @@ L provides an accepted way to separate and group users into categories, and then check which categories the current user belongs to. +=head1 EXAMPLE + +Let's say we were storing users in an apache style htpasswd file. The way users +are stored is in that file, with a hashed password and some extra comments. The +way users are verified is by supplying a password which is matched with the +file. + +This means that our application will begin like this: + + package MyApp; + + use Catalyst qw/ + Authentication + Authentication::Credential::Password + Authentication::Store::Htpasswd + /; + + __PACKAGE__->config->{authentication}{htpasswd} = "passwdfile"; + +This loads the appropriate methods and also sets the htpasswd store as the +default store. + +So, now that we have the code loaded we need to get data from the user into the +credential verifier. + +Let's create an authentication controller: + + package MyApp::Controller::Auth; + + sub login : Local { + my ( $self, $c ) = @_; + + if ( my $user = $c->req->param("user") + and my $password = $c->req->param("password") ) + { + if ( $c->login( $user, $password ) ) { + $c->res->body( "hello " . $c->user->name ); + } else { + # login incorrect + } + } + else { + # invalid form input + } + } + +This code should be very readable. If all the necessary fields are supplied, +call the L method on the +controller. If that succeeds the user is logged in. + +It could be simplified though: + + sub login : Local { + my ( $self, $c ) = @_; + + if ( $c->login ) { + ... + } + } + +Since the C method knows how to find logically named parameters on it's +own. + +The credential verifier will ask the default store to get the user whose ID is +the user parameter. In this case the default store is the htpasswd one. Once it +fetches the user from the store the password is checked and if it's OK +C<< $c->user >> will contain the user object returned from the htpasswd store. + +We can also pass a user object to the credential verifier manually, if we have +several stores per app. This is discussed in +L. + +Now imagine each admin user has a comment set in the htpasswd file saying +"admin". + +A restricted action might look like this: + + sub restricted : Local { + my ( $self, $c ) = @_; + + $c->detach("unauthorized") + unless $c->user_exists + and $c->user->extra_info() eq "admin"; + + # do something restricted here + } + +This is somewhat similar to role based access control. +L treats the extra info +field as a comma separated list of roles if it's treated that way. Let's +leverage this. Add the role authorization plugin: + + use Catalyst qw/ + ... + Authorization::Roles + /; + + sub restricted : Local { + my ( $self, $c ) = @_; + + $c->detach("unauthorized") unless $c->check_roles("admin"); + + # do something restricted here + } + +This is somewhat simpler and will work if you change your store, too, since the +role interface is consistent. + +Let's say your app grew, and you now have 10000 users. It's no longer efficient +to maintain an htpasswd file, so you move this data to a database. + + use Catalyst qw/ + Authentication + Authentication::Credential::Password + Authentication::Store::DBIC + Authorization::Roles + /; + + __PACKAGE__->config->{authentication}{dbic} = ...; # see the DBIC store docs + +The rest of your code should be unchanged. Now let's say you are integrating +typekey authentication to your system. For simplicity's sake we'll assume that +the user's are still keyed in the same way. + + use Catalyst qw/ + Authentication + Authentication::Credential::Password + Authentication::Credential::TypeKey + Authentication::Store::DBIC + Authorization::Roles + /; + +And in your auth controller add a new action: + + sub typekey : Local { + my ( $self, $c ) = @_; + + if ( $c->authenticate_typekey) { # uses $c->req and Authen::TypeKey + # same stuff as the $c->login method + # ... + } + } + +You've now added a new credential verification mechanizm orthogonally to the +other components. All you have to do is make sure that the credential verifiers +pass on the same types of parameters to the store in order to retrieve user +objects. + =head1 METHODS =over 4 @@ -458,6 +606,10 @@ L L, L +=head2 Internals Documentation + +L + =head2 Misc L,