You can checkout the source code for this example from the catalyst
subversion repository as per the instructions in
-L<Catalyst::Manual::Tutorial::Intro>
+L<Catalyst::Manual::Tutorial::Intro|Catalyst::Manual::Tutorial::Intro>.
+
=head1 BASIC AUTHORIZATION
In this section you learn how to manually configure authorization.
+
=head2 Update Plugins to Include Support for Authorization
Edit C<lib/MyApp.pm> and add C<Authorization::Roles> to the list:
- use Catalyst qw/
+ __PACKAGE__->setup(qw/
-Debug
ConfigLoader
Static::Simple
-
+
StackTrace
-
+
Authentication
Authorization::Roles
-
+
Session
Session::Store::FastMmap
Session::State::Cookie
- /;
+ /;
=head2 Add Config Information for Authorization
-Edit C<myapp.conf> and update it to match the following (the
+Edit C<myapp.conf> and update it to match the following (the
C<role_relation> and C<role_field> definitions are new):
+ # rename this file to MyApp.yml and put a : in front of "name" if
+ # you want to use yaml like in old versions of Catalyst
name MyApp
<authentication>
default_realm dbic
<credential>
# Note this first definition would be the same as setting
# __PACKAGE__->config->{authentication}->{realms}->{dbic}
- # ->{credential} = 'Password' in lib/MyApp.pm
+ # ->{credential} = 'Password' in lib/MyApp.pm
#
# Specify that we are going to do password-based auth
class Password
<store>
# Use DBIC to retrieve username, password & role information
class DBIx::Class
- # This is the model object created by Catalyst::Model::DBIC
+ # This is the model object created by Catalyst::Model::DBIC
# from your schema (you created 'MyApp::Schema::User' but as
- # the Catalyst startup debug messages show, it was loaded as
+ # the Catalyst startup debug messages show, it was loaded as
# 'MyApp::Model::DB::Users').
- # NOTE: Omit 'MyApp::Model' here just as you would when using
+ # NOTE: Omit 'MyApp::Model' here just as you would when using
# '$c->model("DB::Users)'
user_class DB::Users
- # This is the name of the field in your 'users' table that
- # contains the user's name
- id_field username
# This is the name of a many_to_many relation in the users
# object that points to the roles for that user
role_relation roles
Open C<root/src/books/list.tt2> in your editor and add the following
lines to the bottom of the file:
- <p>Hello [% Catalyst.user.username %], you have the following roles:</p>
+ <p>Hello [% c.user.username %], you have the following roles:</p>
<ul>
[% # Dump list of roles -%]
- [% FOR role = Catalyst.user.roles %]<li>[% role %]</li>[% END %]
+ [% FOR role = c.user.roles %]<li>[% role %]</li>[% END %]
</ul>
<p>
[% # Add some simple role-specific logic to template %]
[% # Use $c->check_user_roles() to check authz -%]
- [% IF Catalyst.check_user_roles('user') %]
+ [% IF c.check_user_roles('user') %]
[% # Give normal users a link for 'logout' %]
- <a href="[% Catalyst.uri_for('/logout') %]">Logout</a>
+ <a href="[% c.uri_for('/logout') %]">Logout</a>
[% END %]
[% # Can also use $c->user->check_roles() to check authz -%]
- [% IF Catalyst.check_user_roles('admin') %]
+ [% IF c.check_user_roles('admin') %]
[% # Give admin users a link for 'create' %]
- <a href="[% Catalyst.uri_for('form_create') %]">Create</a>
+ <a href="[% c.uri_for('form_create') %]">Create</a>
[% END %]
</p>
This code displays a different combination of links depending on the
roles assigned to the user.
+
=head2 Limit C<Books::add> to C<admin> Users
C<IF> statements in TT templates simply control the output that is sent
updating C<url_create> to match the following code:
=head2 url_create
-
+
Create a book with the supplied title and rating,
with manual authorization
# Check the user's roles
if ($c->check_user_roles('admin')) {
- # Call create() on the book model object. Pass the table
+ # Call create() on the book model object. Pass the table
# columns/field values we want to set as hash values
my $book = $c->model('DB::Books')->create({
title => $title,
rating => $rating
});
-
- # Add a record to the join table for this book, mapping to
+
+ # Add a record to the join table for this book, mapping to
# appropriate author
$book->add_to_book_authors({author_id => $author_id});
# Note: Above is a shortcut for this:
# $book->create_related('book_authors', {author_id => $author_id});
-
+
# Assign the Book object to the stash for display in the view
$c->stash->{book} = $book;
-
+
# This is a hack to disable XSUB processing in Data::Dumper
# (it's used in the view). This is a work-around for a bug in
# the interaction of some versions or Perl, Data::Dumper & DBIC.
# You won't need this if you aren't using Data::Dumper (or if
- # you are running DBIC 0.06001 or greater), but adding it doesn't
+ # you are running DBIC 0.06001 or greater), but adding it doesn't
# hurt anything either.
$Data::Dumper::Useperl = 1;
-
+
# Set the TT template to use
$c->stash->{template} = 'books/create_done.tt2';
} else {
Pod comment. For example, put something like C<=begin> before C<sub add
: Local {> and C<=end> after the closing C<}>.
+
=head2 Try Out Authentication And Authorization
Press C<Ctrl-C> to kill the previous server instance (if it's still
$ script/myapp_server.pl
-Now trying going to L<http://localhost:3000/books/list> and you should
-be taken to the login page (you might have to C<Shift+Reload> your
-browser and/or click the "Logout" link on the book list page). Try
-logging in with both C<test01> and C<test02> (both use a password
-of C<mypass>) and notice how the roles information updates at the
-bottom of the "Book List" page. Also try the C<Logout> link on the
-book list page.
+Now trying going to L<http://localhost:3000/books/list> and you should
+be taken to the login page (you might have to C<Shift+Reload> or
+C<Ctrl+Reload> your browser and/or click the "Logout" link on the book
+list page). Try logging in with both C<test01> and C<test02> (both
+use a password of C<mypass>) and notice how the roles information
+updates at the bottom of the "Book List" page. Also try the C<Logout>
+link on the book list page.
Now the "url_create" URL will work if you are already logged in as user
C<test01>, but receive an authorization failure if you are logged in as
http://localhost:3000/books/url_create/test/1/6
-while logged in as each user. Use one of the 'Logout' links (or go to
-L<http://localhost:3000/logout> in you browser directly) when you are
+while logged in as each user. Use one of the 'Logout' links (or go to
+L<http://localhost:3000/logout> in your browser directly) when you are
done.
This section takes a brief look at how the
L<Catalyst::Plugin::Authorization::ACL|Catalyst::Plugin::Authorization::ACL>
-plugin can automate much of the work required to perform role-based
+plugin can automate much of the work required to perform role-based
authorization in a Catalyst application.
+
=head2 Add the C<Catalyst::Plugin::Authorization::ACL> Plugin
Open C<lib/MyApp.pm> in your editor and add the following plugin to the
-C<use Catalyst> statement:
+C<__PACKAGE__-E<gt>setup> statement:
Authorization::ACL
Note that the remaining C<use Catalyst> plugins from earlier sections
are not shown here, but they should still be included.
+
=head2 Add ACL Rules to the Application Class
Open C<lib/MyApp.pm> in your editor and add the following B<BELOW> the
-C<__PACKAGE__-E<gt>setup;> statement:
+C<__PACKAGE__-E<gt>setup> statement:
# Authorization::ACL Rules
__PACKAGE__->deny_access_unless(
=over 4
-=item *
+=item *
The ACL plugin only operates on the Catalyst "private namespace". You
are using the private namespace when you use C<Local> actions. C<Path>,
C<Regex>, and C<Global> allow you to specify actions where the path and
the namespace differ -- the ACL plugin will not work in these cases.
-=item *
+=item *
Each rule is expressed in a separate
C<__PACKAGE__-E<gt>deny_access_unless()> or
L<Catalyst::Plugin::Authorization::ACL|Catalyst::Plugin::Authorization::ACL>
documentation for more details).
-=item *
+=item *
Each rule can contain multiple roles but only a single path.
-=item *
+=item *
The rules are tried in order (with the "most specific" rules tested
first), and processing stops at the first "match" where an allow or deny
then processing stops there and the appropriate allow/deny action is
taken.
-=item *
+=item *
If none of the rules match, then access is allowed.
-=item *
+=item *
-The rules currently need to be specific in the application class
+The rules currently need to be specified in the application class
C<lib\MyApp.pm> B<after> the C<__PACKAGE__-E<gt>setup;> line.
=back
+
=head2 Add a Method to Handle Access Violations
By default,
$c->forward('list');
}
-Then run the Catalyst development server script:
+Then run the Catalyst development server script:
$ script/myapp_server.pl
Please report any errors, issues or suggestions to the author. The
most recent version of the Catalyst Tutorial can be found at
-L<http://dev.catalyst.perl.org/repos/Catalyst/trunk/Catalyst-Manual/lib/Catalyst/Manual/Tutorial/>.
+L<http://dev.catalyst.perl.org/repos/Catalyst/Catalyst-Manual/5.70/trunk/lib/Catalyst/Manual/Tutorial/>.
Copyright 2006-2008, Kennedy Clark, under Creative Commons License
-(L<http://creativecommons.org/licenses/by-nc-sa/2.5/>).
+(L<http://creativecommons.org/licenses/by-sa/3.0/us/>).