X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FManual%2FTutorial%2FAuthentication.pod;h=b330fd70aec9185601f22a8e1f7b381d1fbe71f2;hb=f2c10d65222a90ee666a98daeff0120508061b52;hp=438bdbdb3042d461e93cd956a1d5fe35603f4def;hpb=64ccd8a8bfbc16276c044c94702b1440c2897695;p=catagits%2FCatalyst-Runtime.git diff --git a/lib/Catalyst/Manual/Tutorial/Authentication.pod b/lib/Catalyst/Manual/Tutorial/Authentication.pod index 438bdbd..b330fd7 100644 --- a/lib/Catalyst/Manual/Tutorial/Authentication.pod +++ b/lib/Catalyst/Manual/Tutorial/Authentication.pod @@ -3,7 +3,6 @@ Catalyst::Manual::Tutorial::Authentication - Catalyst Tutorial - Part 4: Authentication - =head1 OVERVIEW This is B for the Catalyst tutorial. @@ -22,7 +21,7 @@ L =item 3 -L +L =item 4 @@ -46,38 +45,34 @@ L =item 9 -L +L =back - =head1 DESCRIPTION Now that we finally have a simple yet functional application, we can -focus on providing authentication (with authorization coming in Part 5). +focus on providing authentication (with authorization coming next in +Part 5). This part of the tutorial is divided into two main sections: 1) basic, cleartext authentication and 2) hash-based authentication. -B: Note that all of the code for this part of the tutorial can be -pulled from the Catalyst Subversion repository in one step with the -following command: - - svn checkout http://dev.catalyst.perl.org/repos/Catalyst/trunk/examples/Tutorial@### - IMPORTANT: Does not work yet. Will be completed for final version. - - +You can checkout the source code for this example from the catalyst +subversion repository as per the instructions in +L =head1 BASIC AUTHENTICATION -This section explores how add authentication logic to a Catalyst application. +This section explores how to add authentication logic to a Catalyst +application. =head2 Add Users and Roles to the Database -First, we add both user and role information to the database (we add the -role information here although it will not be used until the +First, we add both user and role information to the database (we will +add the role information here although it will not be used until the authorization section, Part 5). Create a new SQL script file by opening C in your editor and insert: @@ -120,10 +115,10 @@ Then load this into the C database with the following command: $ sqlite3 myapp.db < myapp02.sql -=head2 Add User and Role Information to Dbic Schema +=head2 Add User and Role Information to DBIC Schema This step adds DBIC-based classes for the user-related database tables -(the role information will not be used until the Part 5): +(the role information will not be used until Part 5): Edit C and update the contents to match (only the C [qw/Book BookAuthor Author User UserRole Role/]> line @@ -334,16 +329,14 @@ Again, notice that your "result source" classes have been "re-loaded" by Catalys =head2 Include Authentication and Session Plugins -Edit C and update it as follows (everything below C is new): +Edit C and update it as follows (everything below C is new): use Catalyst qw/ -Debug ConfigLoader Static::Simple - Dumper StackTrace - DefaultEnd Authentication Authentication::Store::DBIC @@ -357,8 +350,8 @@ Edit C and update it as follows (everything below C is The three C plugins work together to support Authentication while the C plugins are required to maintain state across multiple HTTP requests. Note that there are several -options for L (although -L +options for L +(L is generally a good choice if you are on Unix; try L if you are on Win32) -- consult L and @@ -370,10 +363,12 @@ its subclasses for additional information. Although C<__PACKAGE__-Econfig(name =E 'value');> is still supported, newer Catalyst applications tend to place all configuration information in C and automatically load this information into -Cconfig> using the -L plugin. - -Edit the C YAML and update it to match: +Cconfig> using the +L plugin. Here, we need +to load several parameters that tell +L +where to locate information in your database. To do this, edit the +C YAML and update it to match: --- name: MyApp @@ -386,7 +381,7 @@ Edit the C YAML and update it to match: # This is the model object created by Catalyst::Model::DBIC from your # schema (you created 'MyAppDB::User' but as the Catalyst startup # debug messages show, it was loaded as 'MyApp::Model::MyAppDB::User'). - # NOTE: Omit 'MyAppDB::Model' to avoid a component lookup issue in Catalyst 5.66 + # NOTE: Omit 'MyApp::Model' to avoid a component lookup issue in Catalyst 5.66 user_class: MyAppDB::User # This is the name of the field in your 'users' table that contains the user's name user_field: username @@ -415,15 +410,21 @@ you could have a C controller with both C and C actions. Remember, Catalyst is designed to be very flexible, and leaves such matters up to you, the designer and programmer. -Then open C and add: +Then open C, locate the C method (this was automatically inserted by the helpers when we +created the Login controller above), and delete this line: + + $c->response->body('Matched MyApp::Controller::Login in Login.'); + +Then update it to match: - =head2 default + =head2 index Login logic =cut - sub default : Private { + sub index : Private { my ($self, $c) = @_; # Get the username and password from form @@ -454,24 +455,47 @@ at the login page but receive an error message. If the C and C values are not present in the form, the user will be taken to the empty login form. -Next, create a corresponding method in C: - - =head2 default +Note that we could have used something like C; +however, the use of C actions is discouraged because it does +not receive path args as with other actions. The recommended practice +is to only use C in C. + +Another option would be to use something like +C (where the C<...> refers to the login +code shown in C above). We are using C here to specifically match the URL C. +C actions (aka, "literal actions") create URI matches relative to +the namespace of the controller where they are defined. Although +C supports arguments that allow relative and absolute paths to be +defined, here we use an empty C definition to match on just the +name of the controller itself. The method name, C, is arbitrary. +We make the match even more specific with the C<:Args(0)> action +modifier -- this forces the match on I C, not +C. + +Next, update the corresponding method in C +to match: + + =head2 index Logout logic =cut - sub default : Private { + sub index : Private { my ($self, $c) = @_; # Clear the user's state $c->logout; - # Send the user to the starting + # Send the user to the starting point $c->response->redirect($c->uri_for('/')); } +As with the login controller, be sure to delete the +C<$c->response->body('Matched MyApp::Controller::Logout in Logout.');> +line of the C. + =head2 Add a Login Form TT Template Page @@ -506,7 +530,8 @@ This is generally done via an C action/method (prior to Catalyst v5.66, this sort of thing would go in C, but starting in v5.66, the preferred location is C). -Edit the existing C class file and insert the following method: +Edit the existing C class file and insert +the following method: =head2 auto @@ -516,11 +541,17 @@ Edit the existing C class file and insert the foll # Note that 'auto' runs after 'begin' but before your actions and that # 'auto' "chain" (all from application path to most specific class are run) + # See the 'Actions' section of 'Catalyst::Manual::Intro' for more info. sub auto : Private { my ($self, $c) = @_; - # Allow unauthenticated users to reach the login page - if ($c->request->path =~ /login/) { + # Allow unauthenticated users to reach the login page. This + # allows anauthenticated users to reach any action in the Login + # controller. To lock it down to a single action, we could use: + # if ($c->action eq $c->controller('Login')->action_for('index')) + # to only allow unauthenticated access to the C action we + # added above. + if ($c->controller eq $c->controller('Login')) { return 1; } @@ -540,9 +571,8 @@ Edit the existing C class file and insert the foll B Catalyst provides a number of different types of actions, such as C, C, and C. You should refer to -L for a more detailed -explanation, but the following bullet points provide a quick -introduction: +L for a more detailed explanation, but the +following bullet points provide a quick introduction: =over 4 @@ -559,9 +589,18 @@ C, C, and C. =item * -Unlike the other private C actions where only a single method -is called for each request, I auto action along the chain of -namespaces will be called. +With C, C, C, C private actions, only the +most specific action of each type will be called. For example, if you +define a C action in your controller it will I a +C action in your application/root controller -- I the +action in your controller will be called. + +=item * + +Unlike the other actions where only a single method is called for each +request, I auto action along the chain of namespaces will be +called. Each C action will be called I. =back @@ -582,7 +621,7 @@ lines to the bottom of the file: # This code illustrates how certain parts of the TT # template will only be shown to users who have logged in %] - [% IF Catalyst.user %] + [% IF Catalyst.user_exists %] Please Note: You are already logged in as '[% Catalyst.user.username %]'. You can logout here. [% ELSE %] @@ -625,30 +664,30 @@ C script.) Now trying going to L and you should be redirected to the login page, hitting Shift+Reload if necessary (the "You are already logged in" message should I appear -- if it does, -click the C button and try again). Make note of the -C<***Root::auto User not found...> debug message in the development -server output. Enter username C and password C, and you -should be taken to the Book List page. +click the C button and try again). Note the C<***Root::auto User +not found...> debug message in the development server output. Enter +username C and password C, and you should be taken to +the Book List page. -Open C< root/src/books/list.tt2> and add the following lines to the bottom: +Open C and add the following lines to the +bottom:

Login Create

-Reload your browser and you should now see a "Login" link at the bottom -of the page (as mentioned earlier, you can update template files without -reloading the development server). Click this link to return to the -login page. This time you I see the "You are already logged in" -message. +Reload your browser and you should now see a "Login" and "Create" links +at the bottom of the page (as mentioned earlier, you can update template +files without reloading the development server). Click the first link +to return to the login page. This time you I see the "You are +already logged in" message. Finally, click the C link on the C page. You should stay at the login page, but the message should change to "You need to log in to use this application." - =head1 USING PASSWORD HASHES In this section we increase the security of our system by converting @@ -660,8 +699,9 @@ tutorial will function normally. Note that even with the techniques shown in this section, the browser still transmits the passwords in cleartext to your application. We are just avoiding the I of cleartext passwords in the database by -using a SHA-1 hash. If you are concerned about cleartext passwords -between the browser and your application, consider using SSL/TLS. +using a SHA-1 hash. If you are concerned about cleartext passwords +between the browser and your application, consider using SSL/TLS, made +easy with the Catalyst plugin Catalyst::Plugin:RequireSSL. =head2 Get a SHA-1 Hash for the Password @@ -676,6 +716,13 @@ dirty" way to do this: e727d1464ae12436e899a726da5b2f11d8381b26 $ +B You should probably modify this code for production use to +not read the password from the command line. By having the script +prompt for the cleartext password, it avoids having the password linger +in forms such as your C<.bash_history> files (assuming you are using +BASH as your shell). An example of such a script can be found in +Appendix 3. + =head2 Switch to SHA-1 Password Hashes in the Database @@ -715,7 +762,8 @@ C are new, everything else is the same): # This is the model object created by Catalyst::Model::DBIC from your # schema (you created 'MyAppDB::User' but as the Catalyst startup # debug messages show, it was loaded as 'MyApp::Model::MyAppDB::User'). - # NOTE: Omit 'MyAppDB::Model' to avoid a component lookup issue in Catalyst 5.66 + # NOTE: Omit 'MyApp::Model' here just as you would when using + # '$c->model("MyAppDB::User)' user_class: MyAppDB::User # This is the name of the field in your 'users' table that contains the user's name user_field: username @@ -739,16 +787,88 @@ You should now be able to go to L and login as before. When done, click the "Logout" link on the login page (or point your browser at L). -=head1 AUTHOR +B If you receive the debug screen in your browser with a +C error message, +make sure that you are using v0.07 of +L. +The following command can be a useful way to quickly dump the version number +of this module on your system: + + perl -MCatalyst::Plugin::Authorization::ACL -e 'print $Catalyst::Plugin::Authorization::ACL::VERSION, "\n";' -Kennedy Clark, C -Please report any errors, issues or suggestions to the author. +=head1 USING THE SESSION FOR FLASH -Copyright 2006, Kennedy Clark. All rights reserved. +As discussed in Part 3 of the tutorial, C allows you to set +variables in a way that is very similar to C, but it will +remain set across multiple requests. Once the value is read, it +is cleared (unless reset). Although C has nothing to do with +authentication, it does leverage the same session plugins. Now that +those plugins are enabled, let's go back and improve the "delete +and redirect with query parameters" code seen at the end of the +C part of the tutorial. -This library is free software; you can redistribute it and/or modify it -under the same terms as Perl itself. +First, open C and modify C +to match the following: + + =head2 delete + + Delete a book + + =cut + + sub delete : Local { + # $id = primary key of book to delete + my ($self, $c, $id) = @_; + + # Search for the book and then delete it + $c->model('MyAppDB::Book')->search({id => $id})->delete_all; + + # Use 'flash' to save information across requests util it's read + $c->flash->{status_msg} = "Book deleted"; + + # Redirect the user back to the list page with status msg as an arg + $c->response->redirect($c->uri_for('/books/list')); + } + +Next, open C update the TT code to pull from flash +vs. the C query parameter: + + + +
+ [% status_msg || Catalyst.flash.status_msg %] + [% error_msg %] + [% content %] +
+ + + + +=head2 Try Out Flash + +Restart the development server and point your browser to +L to create an extra +book. Click the "Return to list" link and delete this "Test" book. +The C mechanism should retain our "Book deleted" status message +across the redirect. + +B While C will save information across multiple requests, +it does get cleared the first time it is read. In general, this is +exactly what you want -- the C message will get displayed on +the next screen where it's appropriate, but it won't "keep showing up" +after that first time (unless you reset it). Please refer to +L for additional +information. + + +=head1 AUTHOR + +Kennedy Clark, C -Version: .94 +Please report any errors, issues or suggestions to the author. The +most recent version of the Catalyst Tutorial can be found at +L. +Copyright 2006, Kennedy Clark, under Creative Commons License +(L).