Catalystでユーザ認証処理をする

Catalystで簡易なユーザ認証処理を実装します。

  • 前提条件
    • MySQL5.0.x


・テーブルとレコード作成

CREATE TABLE users (
   id integer NOT NULL auto_increment PRIMARY KEY,
   username varchar(20) NOT NULL,
   password varchar(30) NOT NULL
) ENGINE=InnoDB;

INSERT INTO users(username, password) VALUES('test01', 'passwd');


・usersテーブルのSchemaを生成する

./script/myapp_create.pl model MyAppDB DBIC::Schema MyAppDB
create=static 'dbi:mysql:test;;mysql_socket=/tmp/mysql.sock' root root
 exists "/who/am/i/MyApp/script/../lib/MyApp/Model"
 exists "/who/am/i/MyApp/script/../t"
Dumping manual schema for MyAppDB to directory
/who/am/i/MyApp/script/../lib ...Schema dump completed.
created "/who/am/i/MyApp/script/../lib/MyApp/Model/DBIC.pm"
 exists "/who/am/i/MyApp/script/../t/model_DBIC.t"

以下のファイルが生成されます

./lib/MyApp/Model/MyAppDB.pm
./lib/MyAppDB.pm
./lib/MyAppDB/Users.pm
./t/model_MyAppDB.t


・設定ファイル(myapp.yml)に認証情報を追加する。

$ vi ./myapp.yml
+authentication:
+    dbic:
+        user_class: MyAppDB::Users
+        user_field: username
+        password_field: password


・アプリケーションクラス(./lib/MyApp.pm)に必要なCPANモジュールを 指定 する。

use Catalyst qw/
       -Debug
       ConfigLoader
       Static::Simple

       StackTrace

       Authentication
       Authentication::Store::DBIC
       Authentication::Credential::Password

       Session
       Session::Store::FastMmap
       Session::State::Cookie
       /;


・Login、Logoutコントローラ生成

$ ./script/myapp_create.pl controller Login
$ ./script/myapp_create.pl controller Logout


・Login(MyApp::Controller::Login)コントローラ編集

sub index : Private {
   my ( $self, $c ) = @_;
   # Get the username and password from form
   my $username = $c->req->param->{username} || '';
   my $password = $c->req->param->{password} || '';

   # If the username and password values were found in form
   if ($username && $password) {
       # Attempt to log the user in
       if ($c->login($username, $password)) {
           # If successful, then let them use the application
           $c->stash->{logined} = 1;
           $c->stash->{username} = $username;
       } else {
           # Set an error message;
           $c->stash->{error_msg} = 'ユーザ名、もしくはパスワードが間違っています';
       }
   }

   $c->stash->{template} = 'login.tt';
}


・Logout(MyApp::Controller::Logout)コントローラ編集

sub index : Private {
   my ( $self, $c ) = @_;

   # Clear the user's state
   $c->logout;

   # Send the user to the starting point
   $c->res->redirect( '/login' );
}


・login.tt(./root/tmpl/login.tt) 作成

[% IF logined %]
 ようこそ [% username %] さん! <br />
 <br />
 ログインに成功しました。<br />
 <br />
[% ELSIF username %]
 [% username %]  さんは既にログインされています。<br />
 <br />
[% ELSE %]
 [% IF error_msg %]
   <font color="red">[% error_msg %]</font>
 [% END %]
[% END %]

   <!-- Login form -->
   <form method="post" action="[% c.uri_for('login') %]">
     <table>
       <tr>
         <td>Username:</td>
         <td><input type="text" name="username" size="40" /></td>
       </tr>
       <tr>
         <td>Password:</td>
         <td><input type="password" name="password" size="40" /></td>
       </tr>
       <tr>
         <td colspan="2"><input type="submit" name="submit"
value="Submit" /></td>
       </tr>
     </table>
   </form>


・コントローラークラスの Root.pm の auto アクションに、セッション情報保持を追加

sub auto : Private {
   my ( $self, $c ) = @_;

   $c->stash->{username} = $c->session->{_user};

   1;
}


・備考
ヘルパースクリプトではまりました。。
他のサイトでは、以下のようにヘルパースクリプトのコマンドが書いてありますが、

script/MyApp_create.pl model DBIC DBIC::Schema MyApp::Schema
create=static dbi:mysql:dbname=MyAppDB MyAppUser Password

自分の環境だと、$c->login を呼んだときに以下のエラーが出ました。他の人は出てないんだろうなぁ。う〜ん。

Caught exception in MyApp::Controller::Login->index "Can't locate
object method "search" via package "MyApp::Schema::Users" at
/where/cpan-lib/lib/perl5/site_perl/5.8.5/Catalyst/Plugin/Authentication/Store/DBIC/User.pm
line 31."

解決策は上述のとおり、ヘルパースクリプトの引数を変更しました。

- script/MyApp_create.pl model DBIC DBIC::Schema MyApp::Schema
create=static dbi:mysql:dbname=MyAppDB MyAppUser Password
+ script/MyApp_create.pl model MyAppDB DBIC::Schema MyAppDB
create=static dbi:mysql:dbname=MyAppDB MyAppUser Password