ユーザ認証とセッション管理のサンプル
Catalyst 5.65 で、下記のプラグインを使って実装してます。
- Catalyst::Plugin::ConfigLoader 0.03
- Catalyst::Plugin::FormValidator::Simple 0.09
- Catalyst::Plugin::FillInForm 0.06
- Catalyst::Plugin::Authentication 0.05
- Catalyst::Plugin::Authentication::Credential::Password
- Catalyst::Plugin::Authentication::Store::DBIC 0.05002
- Catalyst::Plugin::Session 0.05
- Catalyst::Plugin::Session::Store::Memcached 0.02
- Catalyst::Plugin::Session::State::Cookie 0.02
MySql と Memcached は、事前にインストール済みであり、動作している事とします。
Catalyst::Plugin::ConfigLoader を利用しているので、まずは YAML 形式の設定ファイル。
--- name: CatalystMyTest templates: bookmark: default: templates/bookmark/default.tt login: templates/bookmark/login/default.tt validator: plugins: - CreditCard - Japanese options: charset: euc messages: messages.yml authentication: dbic: user_class: CatalystMyTest::Model::DBIC::Member user_field: name password_field: pass use_session: 1 session: expires: 3600 memcached_new_args: data: - localhost:11211
templates は、ボクのオリジナル。今後、パスを解析して自動でテンプレートを選択するように end を書きかえたいと思ってます。
(Oct.12.2006 訂正: DefaultEnd 使った方が良い。また、View::TT を調べた所、template が空の場合は、action 名から template 名を自動生成してくれていた。)
validator は、今回 messages しか使っていないが、今後使う予定があるので一応追加。
他は、各プラグインのマニュアルとソースを確認の事。
authentication の use_session に条件式で真となる値を入れておくと、勝手にセッション管理してくれて楽チン。
validator の messages で指定されている messages.yml
--- login: name: NOT_BLANK: name を入力して下さい ASCII: name は ascii コードで入力して下さい LENGTH: name は 1 〜 10 バイトで入力して下さい pass: NOT_BLANK: pass を入力して下さい ASCII: pass は ascii コードで入力して下さい LENGTH: pass は 4 〜 10 バイトで入力して下さい name_pass: LOGIN: name か pass に誤りがあるので入力しなおして下さい。
次に Catalyst を use している所。
package CatalystMyTest; use strict; use warnings; use Catalyst qw( -Debug ConfigLoader Static::Simple FormValidator::Simple FillInForm Authentication Authentication::Credential::Password Authentication::Store::DBIC Session Session::Store::Memcached Session::State::Cookie ); our $VERSION = '0.01'; __PACKAGE__->setup; sub default : Private { my ( $self, $c ) = @_; # Hello World $c->res->body( $c->welcome_message ); } sub end : Private { my ( $self, $c ) = @_; $c->stash->{template} and !$c->res->body and !$c->res->redirect and $c->forward( $c->view('TT') ); } 1;
Static::Simple は使用していないが、今後使う予定があるので一応追加。
default は、この path 配下でいろいろ試験予定なので、Hello World のまま放置。
end は、body や redirect に何も設定されておらず、templateファイル名が指定されている時のみ、TT を利用するようにしている。(他の方は、どうやってるんだろ?)
で、ログインしたユーザのみ利用できる箇所。
package CatalystMyTest::Controller::Bookmark; use strict; use warnings; use base 'Catalyst::Controller'; sub auto : Private { my ( $self, $c ) = @_; $c->user_exists and return 1; $c->forward( '/bookmark/login/default' ); return 0; } sub default : Private { my ( $self, $c ) = @_; $c->stash->{bookmark_rs} = $c->model( 'DBIC::Bookmark' )->search; $c->stash->{template} = $c->config->{templates}->{bookmark}->{default}; } sub logout : Local { my ( $self, $c ) = @_; $c->logout; $c->forward( '/bookmark/login/default' ); } 1;
auto でユーザ認証を行う。
ここで戻り値として偽値を戻すと、end 以外のメソッドが実行されない。
user_exists で、ログインしているか否か判定可能。
蛇足ですが、ログインしていると
$c->res->body( 'ようこそ' . $c->user->name . 'さん' );
とかが可能です。(当然、name はテーブル内にフィールドがある事が前提)
上記で使用しているテンプレート。
<html> <head><title>[% c.config.name %]</title></head> <body> <a href="/bookmark/logout">logout</a> <hr> [% WHILE (bookmark = bookmark_rs.next) %] <a href="[% bookmark.uri %]">[% bookmark.title %]</a><br> [% END %] </body> </html>
で、最後にログインする箇所。
package CatalystMyTest::Controller::Bookmark::Login; use strict; use warnings; use base 'Catalyst::Controller'; sub default : Private { my ( $self, $c ) = @_; $c->stash->{template} = $c->config->{templates}->{bookmark}->{login}; $c->req->method eq 'GET' and return; $c->form( name => [qw/NOT_BLANK ASCII/, [qw/LENGTH 1 10/]], pass => [qw/NOT_BLANK ASCII/, [qw/LENGTH 4 10/]], ); $c->form->has_error and return; $c->login( $c->req->param('name'), $c->req->param('pass') ) or $c->set_invalid_form( 'name_pass' => 'LOGIN' ); $c->form->has_error and return; $c->forward( '/bookmark/default' ); }
ログイン必要な path が /bookmark で、ログイン不要な path が /bookmark/login になってて、ちょっと変な感じですが、個人勉強用のやっつけなのでご勘弁を。
同じ path で GET と POST で動作を分けてます。
login を使うだけで、ユーザ認証からセッションへの登録まで、全て行ってくれます。
上記で使用しているテンプレート。
<html> <head><title>[% c.config.name %]</title></head> <body> [% IF c.form.has_error %] Input Error <ul> [% FOREACH message IN c.form.messages('login') %] <li>[% message %]</li> [% END %] </ul> [% END %] <form action="/bookmark/login/" method="POST"> <input type="text" name="name"><br> <input type="password" name="pass"><br> <input type="submit" value="login"> </form> </body> </html>
上記例、$c->forward の箇所を、全て $c->res->redirect に変更しても動作する事を確認してます。
ちょっと解り難い説明なので、時間がある時に清書します。