【追記ここから】

vkgtaroさんのコメントで教えていただいたURLを参考に MyApp::Plugin::Session.pm と読込み順番を修正しました。ありがとうございます!!というか、MyApp::Plugin::Session.pm は hidek さんのコードが素晴らしすぎて、最終的にほぼ同じになってしまいました(汗
※一部変更しました(09/06/08)

coderepos に同じような plugin があるよ http://coderepos.org/share/browser/lang/perl/Catalyst-Plugin-Session-DynamicExpiry-Cookie/trunk

【追記ここまで】

先日、Catalystで作ったWebアプリケーションで、オートログイン機能(次回からログインを省略する、とかのチェックボックス)を実装する必要がありました。ので、以下のサイトを参考に実装してみました。

Catalyst でオートログインとブラウザを閉じるまで有効な Cookie を共存させる
C::P::Session::DynamicExpiryを使ってremember me

仕様はこちら。
1. オートログインが無効の場合、ブラウザを閉じたらログイン状態破棄(セッションは30分)
2. オートログインが有効の場合、ブラウザを閉じてもログイン状態維持(セッションは2週間)

この機能は Catalyst::Plugin::Session::DynamicExpiry を使って実現出来るようですね。

そもそも Catalyst::Plugin::Session::State::Cookie を利用する場合、expiresには2種類あります。session の expires と、cookie の expires です。今回は session cookie(ブラウザを閉じるまでのみ有効なcookie )にしたかったので、cookie_expires を 0 としました。YAMLに書くとこんな感じになります。

session:
  expires: 1800 # 指定しなかった場合は 7200
  cookie_expires: 0 # 指定しなかった場合は expires の値が使われる

cookie の expire sは 0 (ブラウザを閉じるまで)、session の expires は30分です。ブラウザを閉じてから開きなおすと、cookie の中のセッションIDが変わるため、新たなセッションが開始されます。

では、ここからいよいよ本題 (*・ω・)ノ

まず、オートログインのチェックボックスがチェックされたとき、session_time_to_live メソッドを呼んであげます。もともと、session のexpires は 1800 でしたが、session_time_to_live メソッドの引数によって自由に変更可能です。

sub login : Local {
    my ($self, $c) = @_;   

    if ( $c->authenticate($userinfo) ) {

        if ( $c->req->param('remember_me') ) {
            $c->session->{autologin} = 1;
            $c->session_time_to_live( 60 * 60 * 24 * 14 ); # 2週間
        }
        
        # ..snip..
    }
}

ログアウトのときには、session_time_to_live メソッドに undef を渡します。これは、Catalyst::Plugin::Session::DynamicExpiry で、このような実装となっているためです。if条件の中に入らないようにしてあげなければいけません。(・∀・)

sub logout : Local {
    my ($self, $c) = @_;

    $c->logout();

    if ( $c->session->{autologin} ) {
        $c->session_time_to_live(undef);
        delete $c->session->{autologin};
        delete $c->session->{cookie_expires};
    }

    $c->res->redirect( $c->uri_for('/') );
}

Catalyst::Plugin::Session::DynamicExpiry.pm
sub calculate_extended_session_expires {
    my $c = shift;

    if ( defined(my $ttl = $c->session_time_to_live) ) {
        $c->log->debug("Overridden time to live: $ttl") if $c->debug;
        return time() + $ttl;
    }

    return $c->NEXT::calculate_extended_session_expires( @_ );
}

ただ、このままでは cookie の expires は 0 のままです。session は2週間の expires を持っていますが、ブラウザを閉じてしまったら結局新たなセッションとなってしまいます。。そこで、cookie の expires は自作のプラグインで変更可能にします。
※以前のものだと、アクセス毎に cookie の expires が伸びてしまうので、セキュリティ的に良くないかと思い、初回のみ cookie の expires が設定される(2週間後)ように変更しました

MyApp::Plugin::Session.pm
package MyApp::Plugin::Session;

use strict;
use warnings;
use parent 'Catalyst::Plugin::Session::DynamicExpiry';

sub calculate_session_cookie_expires {
    my $c = shift;

    if ( defined (my $ttl = $c->session_time_to_live) ) {
        $c->log->debug("Overridden session cookie time to live: $ttl") if $c->debug;
        $c->session->{cookie_expires} ||= ( time() + $ttl );
        return $c->session->{cookie_expires};
    }

    return $c->NEXT::calculate_session_cookie_expires(@_);
}

1;

ちなみに読み込む順番はこんな感じで。
use Catalyst qw/
    +MyApp::Plugin::Session
    Session
    Session::Store::DBIC
    Session::State::Cookie
/;

Catalyst::Plugin::Session::State::Cookie よりも先に 自作のプラグインを読込むので、calculate_session_cookie_expires メソッドが呼ばれたときには、MyApp::Plugin::Session のものが使われます。これで、cookie の expires が session と同じように変更されますね。

これで無事、この仕様を満たすことが出来ました。.。゚+.(・∀・)゚+.゚

1. オートログインが無効の場合、ブラウザを閉じたらログイン状態破棄(セッションは30分)
2. オートログインが有効の場合、ブラウザを閉じてもログイン状態維持(セッションは2週間)
このエントリーをはてなブックマークに追加