Catalyst::Manual::Tutorial::Authentication - Catalyst Tutorial - Part 4: Authentication
-
=head1 OVERVIEW
This is B<Part 4 of 9> for the Catalyst tutorial.
=item 9
-L<Appendicies|Catalyst::Manual::Tutorial::Appendicies>
+L<Appendices|Catalyst::Manual::Tutorial::Appendicies>
=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.
IMPORTANT: Does not work yet. Will be completed for final version.
-
=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<myapp02.sql> in your editor and insert:
$ 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<lib/MyAppDB.pm> and update the contents to match (only the
C<MyAppDB =E<gt> [qw/Book BookAuthor Author User UserRole Role/]> line
ConfigLoader
Static::Simple
- Dumper
StackTrace
DefaultEnd
The three C<Authentication> plugins work together to support
Authentication while the C<Session> plugins are required to maintain
state across multiple HTTP requests. Note that there are several
-options for L<Session::Store|Catalyst::Plugin::Session::Store> (although
-L<Session::Store::FastMmap|Catalyst::Plugin::Session::Store::FastMmap>
+options for L<Session::Store|Catalyst::Plugin::Session::Store>
+(L<Session::Store::FastMmap|Catalyst::Plugin::Session::Store::FastMmap>
is generally a good choice if you are on Unix; try
L<Cache::FileCache|Catalyst::Plugin::Cache::FileCache> if you are on
Win32) -- consult L<Session::Store|Catalyst::Plugin::Session::Store> and
Although C<__PACKAGE__-E<gt>config(name =E<gt> 'value');> is still
supported, newer Catalyst applications tend to place all configuration
information in C<myapp.yml> and automatically load this information into
-C<MyApp-E<gt>config> using the
-L<ConfigLoader|Catalyst::Plugin::ConfigLoader> plugin.
-
-Edit the C<myapp.yml> YAML and update it to match:
+C<MyApp-E<gt>config> using the
+L<ConfigLoader|Catalyst::Plugin::ConfigLoader> plugin. Here, we need
+to load several parameters that tell
+L<Catalyst::Plugin::Authentication|Catalyst::Plugin::Authentication>
+where to locate information in your database. To do this, edit the
+C<myapp.yml> YAML and update it to match:
---
name: MyApp
# 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
Then open C<lib/MyApp/Controller/Login.pm> and add:
- =head2 default
+ =head2 base
Login logic
=cut
- sub default : Private {
+ sub base :Path :Args(0) {
my ($self, $c) = @_;
# Get the username and password from form
C<password> values are not present in the form, the user will be taken
to the empty login form.
+We are using C<sub base :Path :Args(0) {...}> here to specifically match
+the URL C</login>. C<Path> actions (aka, "literal actions") create URI
+matches relative to the namespace of the controller where they are defined.
+Although C<Path> supports arguments that allow relative and absolute paths
+to be defined, here we use an empty C<Path> definition to match on just the
+name of the controller itself. The method name, C<base>, is arbitrary.
+We make the match even more specific with the C<:Args(0)> action modifier
+-- this forces the match on I<only> C</login>, not C</login/somethingelse>.
+
+Note that we could have used something like C<sub default :Private>;
+however, the use of C<default> actions is discouraged because it does
+not receive path args as with other actions. The recommended practice
+is to only use C<default> in C<MyApp::Controller::Root>.
+
Next, create a corresponding method in C<lib/MyApp/Controller/Logout.pm>:
- =head2 default
+ =head2 base
Logout logic
=cut
- sub default : Private {
+ sub base :Path :Args(0) {
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('/'));
}
+Note that we are using the same C<sub base :Path :Args(0) {...}> style
+of action as with the login logic.
+
=head2 Add a Login Form TT Template Page
v5.66, this sort of thing would go in C<MyApp.pm>, but starting in
v5.66, the preferred location is C<lib/MyApp/Controller/Root.pm>).
-Edit the existing C<lib/MyApp/Controller/Root.pm> class file and insert the following method:
+Edit the existing C<lib/MyApp/Controller/Root.pm> class file and insert
+the following method:
=head2 auto
B<Note:> Catalyst provides a number of different types of actions, such
as C<Local>, C<Regex>, and C<Private>. You should refer to
-L<Catalyst::Manual::Intro|Catalyst::Manual::Intro> for a more detailed
-explanation, but the following bullet points provide a quick
-introduction:
+L<Catalyst::Manual::Intro> for a more detailed explanation, but the
+following bullet points provide a quick introduction:
=over 4
=item *
-Unlike the other private C<Private> actions where only a single method
-is called for each request, I<every> auto action along the chain of
-namespaces will be called.
+Unlike the other actions where only a single method is called for each
+request, I<every> auto action along the chain of namespaces will be
+called.
=back
Now trying going to L<http://localhost:3000/books/list> and you should
be redirected to the login page, hitting Shift+Reload if necessary (the
"You are already logged in" message should I<not> appear -- if it does,
-click the C<logout> button and try again). Make note of the
-C<***Root::auto User not found...> debug message in the development
-server output. Enter username C<test01> and password C<mypass>, and you
-should be taken to the Book List page.
+click the C<logout> button and try again). Note the C<***Root::auto User
+not found...> debug message in the development server output. Enter
+username C<test01> and password C<mypass>, 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<root/src/books/list.tt2> and add the following lines to the
+bottom:
<p>
<a href="[% Catalyst.uri_for('/login') %]">Login</a>
<a href="[% Catalyst.uri_for('form_create') %]">Create</a>
</p>
-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<should> 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 this
+link to return to the login page. This time you I<should> see the
+"You are already logged in" message.
Finally, click the C<You can logout here> link on the C</login> 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
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<storage> 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
+L<Catalyst::Plugin:RequireSSL|Catalyst::Plugin:RequireSSL>.
=head2 Get a SHA-1 Hash for the Password
# 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
login as before. When done, click the "Logout" link on the login page
(or point your browser at L<http://localhost:3000/logout>).
+
=head1 AUTHOR
Kennedy Clark, C<hkclark@gmail.com>
Please report any errors, issues or suggestions to the author.
-Copyright 2006, Kennedy Clark. All rights reserved.
-
-This library is free software; you can redistribute it and/or modify it
-under the same terms as Perl itself.
-
-Version: .94
-
+Copyright 2006, Kennedy Clark, under Creative Commons License
+(L<http://creativecommons.org/licenses/by-nc-sa/2.5/>).