Catalystのログイン認証サンプル

Catalystのログイン認証処理を書いてみました。

ドキュメントはここを見ればOKです。

http://search.cpan.org/~mramberg/Catalyst-Runtime-5.7000/lib/Catalyst/Manual/Tutorial/Authentication.pod

OKなんですが、ここにあるサンプルではログインしていないゲストユーザは強制的にログイン画面へリダイレクトするようになってたりします。

「ゲストユーザの人にもサイトの内容を閲覧して欲しい」という場合を想定した一般的なログイン処理のサンプルをつくってみました。

ここにあるサンプルはベーシック認証です。ダイジェスト認証は上記リンク先ドキュメントに説明があるのでそちらを参照して下さい。

#以下のサンプルはCatalyst5.70、DBはMySQLを使用しています。


まずユーザ管理のテーブルを作成します。最低限必要なカラムはusernameとpasswordくらいですね。

create table user (
  id              integer auto_increment primary key,
  username        varchar(15),
  password        varchar(30),
) type=innodb;

設定ファイル(myapp.yml)に認証に関する設定を記述します。

ここではスキーマの指定、認証で使用するユーザ名・パスワードとDBカラムの紐付けを行います。

---
name: MyApp

・・・

authentication:
    dbic:
        user_class: MyApp::Model::DBIC::User
        user_field: username
        password_field: password

アプリケーションクラス(MyApp.pm)に以下のようにuseするモジュールを追加します。

use Catalyst qw/
        -Debug
        ConfigLoader
        Static::Simple

        StackTrace

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

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

次にヘルパースクリプトを利用して、ログイン用のMyApp::Controller::Loginというコントローラクラスを作り、indexアクションを以下のような感じにします。

sub index : Private {

    my ( $self, $c ) = @_;

    my $username = $c->request->params->{username} || "";
    my $password = $c->request->params->{password} || "";

    if ($username && $password) {
        if ($c->login($username, $password)) {
            $c->stash->{logined} = 1;
            $c->stash->{username} = $username;
        } else {
            $c->stash->{error_msg} = "ユーザ名、もしくはパスワードが間違っています。";
        }
    }

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

}

同様にログアウト用のコントローラクラスのMyApp::Controller::Logoutはこんな感じです。

sub index : Private {

    my ( $self, $c ) = @_;

    $c->logout;

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

}

次にコントローラのRootクラス(MyApp::Controller::Root.pm)のautoアクションに以下のような処理を追加します。

セッション変数として持っているログインユーザ名を$c->stashに格納し(無い場合は空)、autoアクション終了後のアクションを継続するために1を返却します。

sub auto : Private {

  my ($self, $c) = @_;

  ・・・・

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

  # User found, so return 1 to continue with processing after this 'auto'
  return 1;

}

TTのテンプレートファイルのサンプルです。

このサンプルではlogin.ttという一つのttファイルをログイン、ログアウトで共通で使用しています。

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

  <!-- Login form -->
  <form method="post" action="/login">
    <table>
      <tr>
        <td>User Name</td>
        <td><input type="text" name="username" size="15" /></td>
      </tr>
      <tr>
        <td>Password</td>
        <td><input type="password" name="password" size="30" /></td>
        <td colspan="2"><input type="submit" name="submit" value="Login" /></td>
      </tr>
    </table>
  </form>
[% END %]

よくあるメニュー内の「ログイン」「ログアウト」の表示は(このサンプルでは)Rootクラスのautoアクションでセッション変数から取得したログインユーザ名で分岐しています。

[% IF username %]
  Hello, [% username %]!<br />
  <a href="/logout">Login</a>
[% ELSE %]
  <a href="/login">Logout</a>
[% END %]

かなり簡素なサンプルですが、初心者の方の参考になればと思います。