Mojoliciousでユーザー認証

**Mojolicious::Guides::Growing** ためしてもなんか上手くいかないので色々試行錯誤してみた結果を残してみる。
ちなみに **Mojolicious::Lite** で書きたかったけど余計にわからなかったのでほぼコピペ（素人）

**2014/3/20 追記。これも面倒くさいなと探していたら[Mojolicious::Plugin::Authentication](https://metacpan.org/pod/Mojolicious::Plugin::Authentication)というプラグインが既にあるみたい。使い方はなんとか把握できたので後日書く。**

**2014/3/23 追記。書いた。
[Mojolicious::Plugin::Authenticationの使い方 - Qiita](http://qiita.com/ymko/items/68f15153793772a041b1)**

![1.png](https://qiita-image-store.s3.amazonaws.com/0/33674/b7919280-b672-1475-9d15-a84d8fc3029b.png)

![2.png](https://qiita-image-store.s3.amazonaws.com/0/33674/7ffc06a9-75cd-4b5b-f1b5-67a08315a1c1.png)

![3.png](https://qiita-image-store.s3.amazonaws.com/0/33674/5e4c66d0-9602-52f0-33fa-0f01450e3bf3.png)

## ひな形生成
第三引数が生成されるプロジェクト名称でPerlの名前空間の先頭大文字である必要があります。

```
$ mojo generate app LoginTest
```

## ルーティング処理
secretは非推奨となっているのでsecretsを使います。
ブリッジでまずアクセスをフックし、認証状態をチェックします。
未認証状態なら後のコントローラーでindexへ飛ばす処理を書いています。

```pl:lib/LoginTest.pm
package LoginTest;
use Mojo::Base 'Mojolicious';

sub startup {
  my $self = shift;
  $self->secrets(['secretword']);

  my $r = $self->routes;

  # ブリッジでどこにアクセスするにも認証チェック
  $r = $r->bridge->to('root#login');

  # '/'は'index'に飛ぶようにする
  $r->any('/')->to('root#index')->name('index');

  # ログアウトはまぁそのまま
  $r->get('/logout')->to('root#logout');
}

1;
```

## コントローラー処理
indexがトップページですが、ルーティング処理でまずはloginが呼ばれます。
セッションの確認、もしくは認証パラメータで成功した場合は正を返し、レタリング処理は行いません。それ以外は認証画面を描画します。

```pl:lib/LoginTest/Root.pm
package LoginTest::Root;
use Mojo::Base 'Mojolicious::Controller';

sub index {
    my $self = shift;
    $self->render(template => 'root/index');
}

sub login {
    my $self = shift;
    my $user = $self->param('user') || '';
    my $pass = $self->param('pass') || '';

    $self->app->log->info("login check");

    # セッション確率済みなら認証通過（適当）
    if ($self->session('user')) {
       return 1;
    }

    # パスワードチェック（適当）
    $self->stash->{auth_failed} = 0;
    if ($user || $pass) {
       $self->app->log->info("pass check");
       if ($user eq "test" && $pass eq "test") {
           $self->session(user => $user);
           return 1;
       }
       $self->stash->{auth_failed} = 1;
    }

    # 認証画面を描画
    $self->render( template => 'root/auth');
    return undef;
}

sub logout {
    my $self = shift;
    # セッション削除
    $self->session(expires => 1);
    $self->redirect_to('index');
}

1;
```

## テンプレート
認証画面で入力されたuser,passをpostします。postを書かないとURLに?user=xxxx&pass=xxxxのように出てしまいます。

```html:/templates/root/auth.html.ep
% layout 'default';

% if ($auth_failed) {
   <b> wrong!</b><br>
% } 

%= form_for index => (method => 'post') => begin
  Name:<br>
  %= text_field 'user'
  <br>Password:<br>
  %= text_field 'pass'
  %= submit_button 'Login'
% end
```

認証が通っていればこの画面がようやく表示されます。
logoutをクリックするとセッションが削除されます。

```html:/templates/root/index.ep
% layout 'default';

Welcome <%= session 'user' %>.<br>
%= link_to Logout => 'logout'
```

#　参考文献（コピペ元）

* [bridgeを活用する](http://qiita.com/yusukebe/items/9f755d17a3a1b657a8b6)
* [Mojoliciousのセッションの話 2013年年末版](http://qiita.com/yusukebe/items/65486fc44b85b4415299)
* [Mojolicious最新版にしたら、Mojolicious::secretは非推奨というログが。](https://twitter.com/kotatsuhal/status/425441927643676672)
* [Mojoliciousですべての処理の前に実行する処理をブリッジで記述する / Mojoliciousリファレンス](http://d.hatena.ne.jp/perlcodesample/20101112/1278596435)