LoginSignup
0
0

More than 5 years have passed since last update.

Perl CGI::Session->load() は呼出毎に最終アクセス時間が更新される(知らなかった

Last updated at Posted at 2017-03-16

WebSocketとCGI::Sessionのハイブリッドシステムで起こる怪奇現象

以前作った「Perl Net::WebSocket::Server + CGI::Session で認証付きソケット作成」のシステムで、接続中の全セッションのタイムアウト処理にCGI::Session->load()を使ってタイムアウト判別を行っていました。

こんなシステムで、セッション管理と有効期限の判別にCGI::Sessionを利用。

誰かがWeb認証経由でWebSocketへアクセスする 
   -> セッションの有効期限が切れてる他のメンバーがいれば強制切断
セッションチェック部分
sub check_session {
    # IPアドレスとポートからセッションIDを取り出す
    my $conn = $_ && $_->can("socket") || !$_[1] ? $_: $_[0];
    my $addr = $conn->socket->peerhost(). ":". $conn->socket->peerport();
    my $sid = $_ && $_->can("socket") || !$_[1] ? $clients{$addr} : $_[1];
    my $session = CGI::Session->load(undef, $sid, {Directory=>'/.session'});
    # 生存チェック
    if (!(defined $session->id) || $sid ne $session->id) {
        $conn->disconnect($conn->socket); #お前はもう死んでいる
        print "dead session: ",$sid,"\n";
        undef $user_ids{$sid};
        undef $clients{$addr}; #セッションIDも消す
        return 0;
    }
    if(!defined($user_ids{$sid})){
        $user_ids{$sid} = $session->param('u');
    }
    return 1;
}

しかしセッションの有効時間中に他のアカウントがアクセスすると、接続中の全セッションの_SESSION_ATIMEが更新されてしまい誰もタイムアウトになりません。

load()関数は有効期限を延長させない」と過信していたのが災いしました・・・。

image
こんな感じで全員同じ時間で更新されてます。orz

やはり、「Node.jsでPerl CGI::Sessionで生成されたSessionIDからセッションを取得する」でやったように、perlでもCGI::Sessionを介さず、直接セッションファイルを読んだほうが確実かもしれませんね・・・。

こんな用途にCGI::Session使う人は少ないと思いますが、アクセス時間を更新しないメソッドを追加して欲しいものです。

追記

CGI-Sessionを使わずにセッションを読む
sub getSession {
    my ($sid, $dir) = @_;
    my $filename = $dir . '/cgisess_' . $sid;
    my $text;
    if (-e $filename) {
        open (my $FILE, "<$filename") or die;
        $text = do { local $/; <$FILE> };
        close($FILE);
    }
    if($text && length($text) > 0){
        my $session = eval($text);
        #現在時刻
        my $now = time;
        #制限時間
        my $limit = $session->{_SESSION_ATIME} + $session->{_SESSION_ETIME};
        #現在時刻が制限時間を超えていたらアウト
        if($now >= $limit){
            return undef;
        }
        return $session;
    } else {
        return undef;
    }
}

ううんダサい。。。他にいい方法はないものか

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0