Cleaned up Tut files; no substantive changes
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Manual / Tutorial / Authentication.pod
CommitLineData
4d583dd8 1=head1 NAME
2
64ccd8a8 3Catalyst::Manual::Tutorial::Authentication - Catalyst Tutorial - Part 4: Authentication
4d583dd8 4
5
6
7=head1 OVERVIEW
8
9This is B<Part 4 of 9> for the Catalyst tutorial.
10
64ccd8a8 11L<Tutorial Overview|Catalyst::Manual::Tutorial>
4d583dd8 12
13=over 4
14
15=item 1
16
17L<Introduction|Catalyst::Manual::Tutorial::Intro>
18
19=item 2
20
21L<Catalyst Basics|Catalyst::Manual::Tutorial::CatalystBasics>
22
23=item 3
24
64ccd8a8 25L<Basic CRUD|Catalyst::Manual::Tutorial_BasicCRUD>
4d583dd8 26
27=item 4
28
29B<Authentication>
30
31=item 5
32
33L<Authorization|Catalyst::Manual::Tutorial::Authorization>
34
35=item 6
36
37L<Debugging|Catalyst::Manual::Tutorial::Debugging>
38
39=item 7
40
41L<Testing|Catalyst::Manual::Tutorial::Testing>
42
43=item 8
44
45L<AdvancedCRUD|Catalyst::Manual::Tutorial::AdvancedCRUD>
46
47=item 9
48
49L<Appendicies|Catalyst::Manual::Tutorial::Appendicies>
50
51=back
52
53
54
55=head1 DESCRIPTION
56
64ccd8a8 57Now that we finally have a simple yet functional application, we can
58focus on providing authentication (with authorization coming in Part 5).
4d583dd8 59
64ccd8a8 60This part of the tutorial is divided into two main sections: 1) basic,
61cleartext authentication and 2) hash-based authentication.
4d583dd8 62
64ccd8a8 63B<TIP>: Note that all of the code for this part of the tutorial can be
64pulled from the Catalyst Subversion repository in one step with the
65following command:
4d583dd8 66
67 svn checkout http://dev.catalyst.perl.org/repos/Catalyst/trunk/examples/Tutorial@###
68 IMPORTANT: Does not work yet. Will be completed for final version.
69
70
71
72=head1 BASIC AUTHENTICATION
73
74This section explores how add authentication logic to a Catalyst application.
75
76
77=head2 Add Users and Roles to the Database
78
64ccd8a8 79First, we add both user and role information to the database (we add the
80role information here although it will not be used until the
81authorization section, Part 5). Create a new SQL script file by opening
82C<myapp02.sql> in your editor and insert:
4d583dd8 83
84 --
85 -- Add users and roles tables, along with a many-to-many join table
86 --
87 CREATE TABLE users (
88 id INTEGER PRIMARY KEY,
89 username TEXT,
90 password TEXT,
91 email_address TEXT,
92 first_name TEXT,
93 last_name TEXT,
94 active INTEGER
95 );
96 CREATE TABLE roles (
97 id INTEGER PRIMARY KEY,
98 role TEXT
99 );
100 CREATE TABLE user_roles (
101 user_id INTEGER,
102 role_id INTEGER,
103 PRIMARY KEY (user_id, role_id)
104 );
105 --
106 -- Load up some initial test data
107 --
108 INSERT INTO users VALUES (1, 'test01', 'mypass', 't01@na.com', 'Joe', 'Blow', 1);
109 INSERT INTO users VALUES (2, 'test02', 'mypass', 't02@na.com', 'Jane', 'Doe', 1);
110 INSERT INTO users VALUES (3, 'test03', 'mypass', 't03@na.com', 'No', 'Go', 0);
111 INSERT INTO roles VALUES (1, 'user');
112 INSERT INTO roles VALUES (2, 'admin');
113 INSERT INTO user_roles VALUES (1, 1);
114 INSERT INTO user_roles VALUES (1, 2);
115 INSERT INTO user_roles VALUES (2, 1);
116 INSERT INTO user_roles VALUES (3, 1);
117
118Then load this into the C<myapp.db> database with the following command:
119
120 $ sqlite3 myapp.db < myapp02.sql
121
122
123=head2 Add User and Role Information to Dbic Schema
124
64ccd8a8 125This step adds DBIC-based classes for the user-related database tables
126(the role information will not be used until the Part 5):
4d583dd8 127
64ccd8a8 128Edit C<lib/MyAppDB.pm> and update the contents to match (only the
129C<MyAppDB =E<gt> [qw/Book BookAuthor Author User UserRole Role/]> line
130has changed):
4d583dd8 131
132 package MyAppDB;
133
134 =head1 NAME
135
136 MyAppDB -- DBIC Schema Class
137
138 =cut
139
140 # Our schema needs to inherit from 'DBIx::Class::Schema'
141 use base qw/DBIx::Class::Schema/;
142
143 # Need to load the DB Model classes here.
144 # You can use this syntax if you want:
145 # __PACKAGE__->load_classes(qw/Book BookAuthor Author User UserRole Role/);
146 # Also, if you simply want to load all of the classes in a directory
147 # of the same name as your schema class (as we do here) you can use:
148 # __PACKAGE__->load_classes(qw//);
149 # But the variation below is more flexible in that it can be used to
150 # load from multiple namespaces.
151 __PACKAGE__->load_classes({
152 MyAppDB => [qw/Book BookAuthor Author User UserRole Role/]
153 });
154
155 1;
156
157
158=head2 Create New "Result Source Objects"
159
160Create the following three files with the content shown below.
161
162C<lib/MyAppDB/User.pm>:
163
164 package MyAppDB::User;
165
166 use base qw/DBIx::Class/;
167
168 # Load required DBIC stuff
169 __PACKAGE__->load_components(qw/PK::Auto Core/);
170 # Set the table name
171 __PACKAGE__->table('users');
172 # Set columns in table
173 __PACKAGE__->add_columns(qw/id username password email_address first_name last_name/);
174 # Set the primary key for the table
175 __PACKAGE__->set_primary_key('id');
176
177 #
178 # Set relationships:
179 #
180
181 # has_many():
182 # args:
183 # 1) Name of relationship, DBIC will create accessor with this name
184 # 2) Name of the model class referenced by this relationship
185 # 3) Column name in *foreign* table
186 __PACKAGE__->has_many(map_user_role => 'MyAppDB::UserRole', 'user_id');
187
188
189 =head1 NAME
190
191 MyAppDB::User - A model object representing a person with access to the system.
192
193 =head1 DESCRIPTION
194
195 This is an object that represents a row in the 'users' table of your application
196 database. It uses DBIx::Class (aka, DBIC) to do ORM.
197
198 For Catalyst, this is designed to be used through MyApp::Model::MyAppDB.
199 Offline utilities may wish to use this class directly.
200
201 =cut
202
203 1;
204
205
206C<lib/MyAppDB/Role.pm>:
207
208 package MyAppDB::Role;
209
210 use base qw/DBIx::Class/;
211
212 # Load required DBIC stuff
213 __PACKAGE__->load_components(qw/PK::Auto Core/);
214 # Set the table name
215 __PACKAGE__->table('roles');
216 # Set columns in table
217 __PACKAGE__->add_columns(qw/id role/);
218 # Set the primary key for the table
219 __PACKAGE__->set_primary_key('id');
220
221 #
222 # Set relationships:
223 #
224
225 # has_many():
226 # args:
227 # 1) Name of relationship, DBIC will create accessor with this name
228 # 2) Name of the model class referenced by this relationship
229 # 3) Column name in *foreign* table
230 __PACKAGE__->has_many(map_user_role => 'MyAppDB::UserRole', 'role_id');
231
232
233 =head1 NAME
234
235 MyAppDB::Role - A model object representing a class of access permissions to
236 the system.
237
238 =head1 DESCRIPTION
239
240 This is an object that represents a row in the 'roles' table of your
241 application database. It uses DBIx::Class (aka, DBIC) to do ORM.
242
243 For Catalyst, this is designed to be used through MyApp::Model::MyAppDB.
244 "Offline" utilities may wish to use this class directly.
245
246 =cut
247
248 1;
249
250
251C<lib/MyAppDB/UserRole.pm>:
252
253 package MyAppDB::UserRole;
254
255 use base qw/DBIx::Class/;
256
257 # Load required DBIC stuff
258 __PACKAGE__->load_components(qw/PK::Auto Core/);
259 # Set the table name
260 __PACKAGE__->table('user_roles');
261 # Set columns in table
262 __PACKAGE__->add_columns(qw/user_id role_id/);
263 # Set the primary key for the table
264 __PACKAGE__->set_primary_key(qw/user_id role_id/);
265
266 #
267 # Set relationships:
268 #
269
270 # belongs_to():
271 # args:
272 # 1) Name of relationship, DBIC will create accessor with this name
273 # 2) Name of the model class referenced by this relationship
274 # 3) Column name in *this* table
275 __PACKAGE__->belongs_to(user => 'MyAppDB::User', 'user_id');
276
277 # belongs_to():
278 # args:
279 # 1) Name of relationship, DBIC will create accessor with this name
280 # 2) Name of the model class referenced by this relationship
281 # 3) Column name in *this* table
282 __PACKAGE__->belongs_to(role => 'MyAppDB::Role', 'role_id');
283
284
285 =head1 NAME
286
287 MyAppDB::UserRole - A model object representing the JOIN between Users and Roles.
288
289 =head1 DESCRIPTION
290
291 This is an object that represents a row in the 'user_roles' table of your application
292 database. It uses DBIx::Class (aka, DBIC) to do ORM.
293
294 You probably won't need to use this class directly -- it will be automatically
295 used by DBIC where joins are needed.
296
297 For Catalyst, this is designed to be used through MyApp::Model::MyAppDB.
298 Offline utilities may wish to use this class directly.
299
300 =cut
301
302 1;
303
304The code for these three result source classes is obviously very familiar to the C<Book>, C<Author>, and C<BookAuthor> classes created in Part 2.
305
306
307=head2 Sanity-Check Reload of Development Server
308
309We aren't ready to try out the authentication just yet; we only want to do a quick check to be sure our model loads correctly. Press C<Ctrl-C> to kill the previous server instance (if it's still running) and restart it:
310
311 $ script/myapp_server.pl
312
313Look for the three new model objects in the startup debug output:
314
315 ...
316 .-------------------------------------------------------------------+----------.
317 | Class | Type |
318 +-------------------------------------------------------------------+----------+
319 | MyApp::Controller::Books | instance |
320 | MyApp::Controller::Root | instance |
321 | MyApp::Model::MyAppDB | instance |
322 | MyApp::Model::MyAppDB::Author | class |
323 | MyApp::Model::MyAppDB::Book | class |
324 | MyApp::Model::MyAppDB::BookAuthor | class |
325 | MyApp::Model::MyAppDB::Role | class |
326 | MyApp::Model::MyAppDB::User | class |
327 | MyApp::Model::MyAppDB::UserRole | class |
328 | MyApp::View::TT | instance |
329 '-------------------------------------------------------------------+----------'
330 ...
331
332Again, notice that your "result source" classes have been "re-loaded" by Catalyst under C<MyApp::Model>.
333
334
335=head2 Include Authentication and Session Plugins
336
337Edit C<lib/MyApp.pm> and update it as follows (everything below C<DefaultEnd> is new):
338
339 use Catalyst qw/
340 -Debug
341 ConfigLoader
342 Static::Simple
343
344 Dumper
345 StackTrace
346 DefaultEnd
347
348 Authentication
349 Authentication::Store::DBIC
350 Authentication::Credential::Password
351
352 Session
353 Session::Store::FastMmap
354 Session::State::Cookie
355 /;
356
64ccd8a8 357The three C<Authentication> plugins work together to support
358Authentication while the C<Session> plugins are required to maintain
359state across multiple HTTP requests. Note that there are several
360options for L<Session::Store|Catalyst::Plugin::Session::Store> (although
361L<Session::Store::FastMmap|Catalyst::Plugin::Session::Store::FastMmap>
362is generally a good choice if you are on Unix; try
363L<Cache::FileCache|Catalyst::Plugin::Cache::FileCache> if you are on
364Win32) -- consult L<Session::Store|Catalyst::Plugin::Session::Store> and
365its subclasses for additional information.
4d583dd8 366
367
368=head2 Configure Authentication
369
64ccd8a8 370Although C<__PACKAGE__-E<gt>config(name =E<gt> 'value');> is still
371supported, newer Catalyst applications tend to place all configuration
372information in C<myapp.yml> and automatically load this information into
373C<MyApp-E<gt>config> using the
374L<ConfigLoader|Catalyst::Plugin::ConfigLoader> plugin.
4d583dd8 375
376Edit the C<myapp.yml> YAML and update it to match:
377
378 ---
379 name: MyApp
380 authentication:
381 dbic:
382 # Note this first definition would be the same as setting
383 # __PACKAGE__->config->{authentication}->{dbic}->{user_class} = 'MyAppDB::User'
384 # in lib/MyApp.pm (IOW, each hash key becomes a "name:" in the YAML file).
385 #
386 # This is the model object created by Catalyst::Model::DBIC from your
387 # schema (you created 'MyAppDB::User' but as the Catalyst startup
388 # debug messages show, it was loaded as 'MyApp::Model::MyAppDB::User').
389 # NOTE: Omit 'MyAppDB::Model' to avoid a component lookup issue in Catalyst 5.66
390 user_class: MyAppDB::User
391 # This is the name of the field in your 'users' table that contains the user's name
392 user_field: username
393 # This is the name of the field in your 'users' table that contains the password
394 password_field: password
395 # Other options can go here for hashed passwords
396
397Inline comments in the code above explain how each field is being used.
398
64ccd8a8 399B<TIP>: Although YAML uses a very simple and easy-to-ready format, it
400does require the use of a consistent level of indenting. Be sure you
401line up everything on a given 'level' with the same number of indents.
402Also, be sure not to use C<tab> characters (YAML does not support them
403because they are handled inconsistently across editors).
4d583dd8 404
405
406=head2 Add Login and Logout Controllers
407
408Use the Catalyst create script to create two stub controller files:
409
410 $ script/myapp_create.pl controller Login
411 $ script/myapp_create.pl controller Logout
412
64ccd8a8 413B<NOTE>: You could easily use a single controller here. For example,
414you could have a C<User> controller with both C<login> and C<logout>
415actions. Remember, Catalyst is designed to be very flexible, and leaves
416such matters up to you, the designer and programmer.
4d583dd8 417
418Then open C<lib/MyApp/Controller/Login.pm> and add:
419
420 =head2 default
421
422 Login logic
423
424 =cut
425
426 sub default : Private {
427 my ($self, $c) = @_;
428
429 # Get the username and password from form
430 my $username = $c->request->params->{username} || "";
431 my $password = $c->request->params->{password} || "";
432
433 # If the username and password values were found in form
434 if ($username && $password) {
435 # Attempt to log the user in
436 if ($c->login($username, $password)) {
437 # If successful, then let them use the application
438 $c->response->redirect($c->uri_for('/books/list'));
439 return;
440 } else {
441 # Set an error message
442 $c->stash->{error_msg} = "Bad username or password.";
443 }
444 }
445
446 # If either of above don't work out, send to the login page
447 $c->stash->{template} = 'login.tt2';
448 }
449
64ccd8a8 450This controller fetches the C<username> and C<password> values from the
451login form and attempts to perform a login. If successful, it redirects
452the user to the book list page. If the login fails, the user will stay
453at the login page but receive an error message. If the C<username> and
454C<password> values are not present in the form, the user will be taken
455to the empty login form.
4d583dd8 456
457Next, create a corresponding method in C<lib/MyApp/Controller/Logout.pm>:
458
459 =head2 default
460
461 Logout logic
462
463 =cut
464
465 sub default : Private {
466 my ($self, $c) = @_;
467
468 # Clear the user's state
469 $c->logout;
470
471 # Send the user to the starting
472 $c->response->redirect($c->uri_for('/'));
473 }
474
475
476=head2 Add a Login Form TT Template Page
477
478Create a login form by opening C<root/src/login.tt2> and inserting:
479
480 [% META title = 'Login' %]
481
482 <!-- Login form -->
483 <form method="post" action=" [% Catalyst.uri_for('/login') %] ">
484 <table>
485 <tr>
486 <td>Username:</td>
487 <td><input type="text" name="username" size="40" /></td>
488 </tr>
489 <tr>
490 <td>Password:</td>
491 <td><input type="password" name="password" size="40" /></td>
492 </tr>
493 <tr>
494 <td colspan="2"><input type="submit" name="submit" value="Submit" /></td>
495 </tr>
496 </table>
497 </form>
498
499
500=head2 Add Valid User Check
501
64ccd8a8 502We need something that provides enforcement for the authentication
503mechanism -- a I<global> mechanism that prevents users who have not
504passed authentication from reaching any pages except the login page.
505This is generally done via an C<auto> action/method (prior to Catalyst
506v5.66, this sort of thing would go in C<MyApp.pm>, but starting in
507v5.66, the preferred location is C<lib/MyApp/Controller/Root.pm>).
4d583dd8 508
509Edit the existing C<lib/MyApp/Controller/Root.pm> class file and insert the following method:
510
511 =head2 auto
512
513 Check if there is a user and, if not, forward to login page
514
515 =cut
516
517 # Note that 'auto' runs after 'begin' but before your actions and that
518 # 'auto' "chain" (all from application path to most specific class are run)
519 sub auto : Private {
520 my ($self, $c) = @_;
521
522 # Allow unauthenticated users to reach the login page
523 if ($c->request->path =~ /login/) {
524 return 1;
525 }
526
527 # If a user doesn't exist, force login
528 if (!$c->user_exists) {
529 # Dump a log message to the development server debug output
530 $c->log->debug('***Root::auto User not found, forwarding to /login');
531 # Redirect the user to the login page
532 $c->response->redirect($c->uri_for('/login'));
533 # Return 0 to cancel 'post-auto' processing and prevent use of application
534 return 0;
535 }
536
537 # User found, so return 1 to continue with processing after this 'auto'
538 return 1;
539 }
540
64ccd8a8 541B<Note:> Catalyst provides a number of different types of actions, such
542as C<Local>, C<Regex>, and C<Private>. You should refer to
543L<Catalyst::Manual::Intro|Catalyst::Manual::Intro> for a more detailed
544explanation, but the following bullet points provide a quick
545introduction:
4d583dd8 546
547=over 4
548
549=item *
550
64ccd8a8 551The majority of application use C<Local> actions for items that respond
552to user requests and C<Private> actions for those that do not directly
553respond to user input.
4d583dd8 554
555=item *
556
64ccd8a8 557There are five types of C<Private> actions: C<begin>, C<end>,
558C<default>, C<index>, and C<auto>.
4d583dd8 559
560=item *
561
64ccd8a8 562Unlike the other private C<Private> actions where only a single method
563is called for each request, I<every> auto action along the chain of
564namespaces will be called.
4d583dd8 565
566=back
567
64ccd8a8 568By placing the authentication enforcement code inside the C<auto> method
569of C<lib/MyApp/Controller/Root.pm> (or C<lib/MyApp.pm>), it will be
570called for I<every> request that is received by the entire application.
4d583dd8 571
572
573=head2 Displaying Content Only to Authenticated Users
574
64ccd8a8 575Let's say you want to provide some information on the login page that
576changes depending on whether the user has authenticated yet. To do
577this, open C<root/src/login.tt2> in your editor and add the following
578lines to the bottom of the file:
4d583dd8 579
580 <p>
581 [%
582 # This code illustrates how certain parts of the TT
583 # template will only be shown to users who have logged in
584 %]
585 [% IF Catalyst.user %]
586 Please Note: You are already logged in as '[% Catalyst.user.username %]'.
587 You can <a href="[% Catalyst.uri_for('/logout') %]">logout</a> here.
588 [% ELSE %]
589 You need to log in to use this application.
590 [% END %]
591 [%#
592 Note that this whole block is a comment because the "#" appears
593 immediate after the "[%" (with no spaces in between). Although it
594 can be a handy way to temporarily "comment out" a whole block of
595 TT code, it's probably a little too subtle for use in "normal"
596 comments.
597 %]
598
64ccd8a8 599Although most of the code is comments, the middle few lines provide a
600"you are already logged in" reminder if the user returns to the login
601page after they have already authenticated. For users who have not yet
602authenticated, a "You need to log in..." message is displayed (note the
603use of an IF-THEN-ELSE construct in TT).
4d583dd8 604
605
606=head2 Try Out Authentication
607
64ccd8a8 608Press C<Ctrl-C> to kill the previous server instance (if it's still
609running) and restart it:
4d583dd8 610
611 $ script/myapp_server.pl
612
64ccd8a8 613B<IMPORTANT NOTE>: If you happen to be using Internet Explorer, you may
614need to use the command C<script/myapp_server.pl -k> to enable the
615keepalive feature in the development server. Otherwise, the HTTP
616redirect on successful login may not work correctly with IE (it seems to
617work without -k if you are running the web browser and development
618server on the same machine). If you are using browser a browser other
619than IE, it should work either way. If you want to make keepalive the
620default, you can edit C<script/myapp_server.pl> and change the
621initialization value for C<$keepalive> to C<1>. (You will need to do
622this every time you create a new Catalyst application or rebuild the
623C<myapp_server.pl> script.)
624
625Now trying going to L<http://localhost:3000/books/list> and you should
626be redirected to the login page, hitting Shift+Reload if necessary (the
627"You are already logged in" message should I<not> appear -- if it does,
628click the C<logout> button and try again). Make note of the
629C<***Root::auto User not found...> debug message in the development
630server output. Enter username C<test01> and password C<mypass>, and you
631should be taken to the Book List page.
4d583dd8 632
633Open C< root/src/books/list.tt2> and add the following lines to the bottom:
634
635 <p>
636 <a href="[% Catalyst.uri_for('/login') %]">Login</a>
637 <a href="[% Catalyst.uri_for('form_create') %]">Create</a>
638 </p>
639
64ccd8a8 640Reload your browser and you should now see a "Login" link at the bottom
641of the page (as mentioned earlier, you can update template files without
642reloading the development server). Click this link to return to the
643login page. This time you I<should> see the "You are already logged in"
644message.
4d583dd8 645
64ccd8a8 646Finally, click the C<You can logout here> link on the C</login> page.
647You should stay at the login page, but the message should change to "You
648need to log in to use this application."
4d583dd8 649
650
651
652=head1 USING PASSWORD HASHES
653
64ccd8a8 654In this section we increase the security of our system by converting
655from cleartext passwords to SHA-1 password hashes.
4d583dd8 656
64ccd8a8 657B<Note:> This section is optional. You can skip it and the rest of the
658tutorial will function normally.
4d583dd8 659
64ccd8a8 660Note that even with the techniques shown in this section, the browser
661still transmits the passwords in cleartext to your application. We are
662just avoiding the I<storage> of cleartext passwords in the database by
663using a SHA-1 hash. If you are concerned about cleartext passwords
664between the browser and your application, consider using SSL/TLS.
4d583dd8 665
666
667=head2 Get a SHA-1 Hash for the Password
668
64ccd8a8 669Catalyst uses the C<Digest> module to support a variety of hashing
670algorithms. Here we will use SHA-1 (SHA = Secure Hash Algorithm).
671First, we should compute the SHA-1 hash for the "mypass" password we are
672using. The following command-line Perl script provides a "quick and
673dirty" way to do this:
4d583dd8 674
675 $ perl -MDigest::SHA -e 'print Digest::SHA::sha1_hex("mypass"), "\n"'
676 e727d1464ae12436e899a726da5b2f11d8381b26
677 $
678
679
680=head2 Switch to SHA-1 Password Hashes in the Database
681
64ccd8a8 682Next, we need to change the C<password> column of our C<users> table to
683store this hash value vs. the existing cleartext password. Open
684C<myapp03.sql> in your editor and enter:
4d583dd8 685
686 --
687 -- Convert passwords to SHA-1 hashes
688 --
689 UPDATE users SET password = 'e727d1464ae12436e899a726da5b2f11d8381b26' WHERE id = 1;
690 UPDATE users SET password = 'e727d1464ae12436e899a726da5b2f11d8381b26' WHERE id = 2;
691 UPDATE users SET password = 'e727d1464ae12436e899a726da5b2f11d8381b26' WHERE id = 3;
692
693Then use the following command to update the SQLite database:
694
695 $ sqlite3 myapp.db < myapp03.sql
696
64ccd8a8 697B<Note:> We are using SHA-1 hashes here, but many other hashing
698algorithms are supported. See C<Digest> for more information.
4d583dd8 699
700
64ccd8a8 701=head2 Enable SHA-1 Hash Passwords in
702C<Catalyst::Plugin::Authentication::Store::DBIC>
4d583dd8 703
64ccd8a8 704Edit C<myapp.yml> and update it to match (the C<password_type> and
705C<password_hash_type> are new, everything else is the same):
4d583dd8 706
707 ---
708 name: MyApp
709 authentication:
710 dbic:
711 # Note this first definition would be the same as setting
712 # __PACKAGE__->config->{authentication}->{dbic}->{user_class} = 'MyAppDB::User'
713 # in lib/MyApp.pm (IOW, each hash key becomes a "name:" in the YAML file).
714 #
715 # This is the model object created by Catalyst::Model::DBIC from your
716 # schema (you created 'MyAppDB::User' but as the Catalyst startup
717 # debug messages show, it was loaded as 'MyApp::Model::MyAppDB::User').
718 # NOTE: Omit 'MyAppDB::Model' to avoid a component lookup issue in Catalyst 5.66
719 user_class: MyAppDB::User
720 # This is the name of the field in your 'users' table that contains the user's name
721 user_field: username
722 # This is the name of the field in your 'users' table that contains the password
723 password_field: password
724 # Other options can go here for hashed passwords
725 # Enabled hashed passwords
726 password_type: hashed
727 # Use the SHA-1 hashing algorithm
728 password_hash_type: SHA-1
729
730
731=head2 Try Out the Hashed Passwords
732
64ccd8a8 733Press C<Ctrl-C> to kill the previous server instance (if it's still
734running) and restart it:
4d583dd8 735
736 $ script/myapp_server.pl
737
64ccd8a8 738You should now be able to go to L<http://localhost:3000/books/list> and
739login as before. When done, click the "Logout" link on the login page
740(or point your browser at L<http://localhost:3000/logout>).
4d583dd8 741
742=head1 AUTHOR
743
744Kennedy Clark, C<hkclark@gmail.com>
745
746Please report any errors, issues or suggestions to the author.
747
748Copyright 2006, Kennedy Clark. All rights reserved.
749
64ccd8a8 750This library is free software; you can redistribute it and/or modify it
751under the same terms as Perl itself.
4d583dd8 752
753Version: .94
754