MP0

MPがありません。

Plack::Middleware::Session まとめ

Plack::Middleware::Session と関連することについてのまとめ、ほぼ個人的なメモ
簡単にまとめるつもりだったけど詳しく書くとかなり長くなりそうな気がしてきた...

使い方

  use Plack::Builder;
  builder {
      enable Session => (
          state => Plack::Session::State::*->new,
          store => Plack::Session::Store::*->new,
      );
      $app;
  };

Middlewareを使うときにPlack::Session::Stateを継承したクラスのインスタンスPlack::Session::Storeを継承したクラスのインスタンスを渡す。
何も渡さない場合のデフォルトの引数は以下のようになる

state => Plack::Session::State::Cookie->new(session_key => 'plack_session'),
store => Plack::Session::Store::File->new(
    dir          => $ENV{TMPDIR} || '/tmp',
    serializer   => sub { Storable::lock_nstore( @_ ) },
    deserializer => sub { Storable::lock_retrieve( @_ ) },
),

stateの方はPlack::Session::State::Cookieが使われていて、バックエンドは普通のクッキーだけど、クッキーの有効期限だとかが指定されていないので、
試しに動かしているみたいな時以外はPlack::Session::State::Cookieのドキュメントをちゃんとみて指定したほうがいいと思う。

storeの方はPlack::Session::Store::Fileが使われていて、バックエンドにはStorableが使われている。セッションの保管場所はちゃんと指定しておくべき
Plack::Session::Storeのバックエンドは他に標準でDBI, Cacheのがあって、好みや用途で使いわけられるし、CPANにはRedisバックエンドのモジュールがあったり、なんなら自分でPlack::Session::Storeを継承した独自のモジュールを作って使うこともできる。

Mojoliciousで使う

有名だけど、Mojoliciousのセッション機能はセキュリティ的に貧弱というかそもそもセッションといえないような感じなので、
Mojoliciousで開発しているときでもPlack::Middleware::Sessionを使いたい場面が多い。
鉄板なのはMojoliciousアプリをPSGIアプリとして起動させてPlack::Middleware::Sessionを使う方法だけど、
これだとPSGIサーバーを使わなければならなくなるので、まだどのサーバーを使うか決めていない場合や開発時にMojolicious組み込みのサーバーを使って開発を進めていきたいときなんかは、
Mojolicious::Plugin::PlackMiddlewareというプラグインがあるのでそれを使ってPlack::Middleware::Sessionを使うといい。
(もしかしたらすべてのPlack::Middlewareは動かないかもしれないが少なくともSessionは使えた)

これを使ったログイン機能のMojolicousでの実装例

ORMにTengかAnikiを使っているとする。
本格的なコードでないのであしからず...(あとでちゃんと動くのをあげる)

sub auth {
    my $self = shift;
    $self->plack_session->get('user_id') ? 1 : 0;
}

sub login {
    my $self = shift;
    my $user_id = $self->param('id');
    my $user = $self->db->select('users', {id => $user_id});
    if ( $user->password eq $self->param('password') ) {
        $self->plack_session->set(change_id => 1);
        $self->plack_session->set(user_id => $user->id);
        $self->render(text => 'success');
    } else {
        $self->render(text => 'fail');
    }
}

sub logout {
    my $self = shift;
    $self->plack_session->expire;
}

Plack::Sessionを使うモジュールのテスト

Plack::Sessionのインスタンスを生成するときは要はキーpsgix.sessionにPlack::Session::Stateのインスタンスが格納されていて、キーpsgix.session.optionsにPlack::Session::Storeのインスタンスが格納されているハッシュリファレンスを渡せばよいので、
次のような感じでPlack::Sessionのインスタンスを作ってテストすればいい。

Plack::Session->new({
      'psgix.session'         => Plack::Session::State::Cookie->new(session_key => 'myapp_sid'),
      'psgix.session.options' => Plack::Session::Store::File->new(dir => './etc/sessions'),
})

まだわかってなさそうなところがあるので、間違ってたりしているところがあれば指摘していただけると嬉しいです。