Perlでセッション機能の実現、CGI::Sessionを用いたセッション管理

ゲームを開発していた時に、一つの壁となったのがセッション管理。
これは不正アクセス対策のために、どうしても導入が必要だった。

ゲームを制作した後から分かったことだが、
PHPとPerlでは、PHPの方がセッションについては遥かに簡単だ。
なぜなら、PHPはセッション機能がデフォルトで組み込まれているから、
その点Perlはセッション管理用のモジュールを、
CPANから引っ張って来なければならない。
そのためレンタルサーバー同等の環境で、
セッション機能を実現したければ、PHPでの開発を推奨する。
私はゲーム開発にあたってさくらVPSを利用しているので、
今回はセッション管理の実装においてのポイントを書いてみる。

CGI::Sessionについて

Perlでは「CGI::Session」というモジュールを利用する。
まず、これはCPANコマンドが使えれば、CPANから簡単に構築できる。
セッション管理にはセッションIDが存在し、
ユーザー側とサーバー側で、そのセッションIDを照合して管理を行う。
ユーザー側からサーバーへセッションIDを送る際、
Cookieを用いる方法と、hiddenパラメータで受け渡す方法がある。
どちらも利点はあるが、私はゲームの性質上Cookieを使っている。
基本的にGETパラメータ等、URLにセッションIDを入れるのはNG。
これはセキュリティ上の観点なので注意されたし。
サーバー側はセッションファイル保存用のディレクトリを必ず用意する。
この辺りの設定を間違えたりすると、途端にスクリプトが動かなくなる。

以下は基本的な機能を使用するためのコード一例(Cookieの場合)

#モジュール使用宣言(CGIも必要なのでなかったら入れておく)
use CGI;
use CGI::Session;

my $session_dir = "★セッションファイル格納ディレクトリパス★";
my $session; #セッション変数格納用
my $sid; #セッションID格納用
my $flag;

#★セッションを作成する時は以下のような感じ

#新規セッション開始
$session = new CGI::Session(undef,undef,{Directory=>"$session_dir"});
#セッション有効時間設定(サンプルは30分を超えるとセッション期限切れ)
$session->expire("+1800s");
#データも格納可能。(サンプルはsession_flagというキーにokという値を格納)
$session->param("session_flag","ok");
#セッションIDを$sidに格納
$sid = $session->id();

$sidをCookieに格納する処理を行う

#★セッションを読み込む時はこんな感じ

CookieからセッションIDを取り出して$sidに格納しておく

#セッションの読み込み(newではなくloadとなっていることに注目)
$session = load CGI::Session(undef,$sid,{Directory=>"$session_dir"});
#セッションIDからデータ取得($flagにsession_flagの値を格納する)
if($session){
    $flag = $session->param("session_flag");
}

#★アクセス判定処理の一例

if($flag ne "ok"){
    print "セッションが確認できませんでした。";
    exit;
}

#★セッションデリートは以下の感じ(セッションファイルは削除される)

if($session){
    $session->delete();
} 

とまぁ、大体こんな感じで基本的な動きはしてくれる。
セッションファイルに格納される値は、
サーバー側のセッションファイルに直に書き込まれているので、
いろいろなデータを格納することができる。
しかも、ファイルはサーバー側が管理しているので比較的安全。

ただし、セッションデリートはユーザーがブラウザを閉じたり、
期待した動きでセッションを終えてくれないと、
セッションディレクトリにセッションファイルが無限に増えていく。
従って、追加で強く推奨するというか、まず必要なのが、
「CGI::Session::ExpireSessions」の導入である。
このモジュールは、不要なセッションファイルを時間判定で削除することができる。
このモジュールもCPANから落として構築できる。
使い方は簡単。以下のような感じだ。

#モジュール使用宣言
use CGI::Session::ExpireSessions;
#不要なセッション削除(サンプルは1800秒の無更新で自動削除)
CGI::Session::ExpireSessions -> new(temp_dir => "$session_dir", delta => 1800 ) -> expire_file_sessions();

あんまりこれを実行すると負荷が掛かるかもしれない。
従って私は要所(ログイン時、アプリケーション終了時等)に実行するようにしている。

今回の記事のサンプルコードがどっか間違ってたらゴメンちゃい。
でも、Perlのセッション管理って、
PHPを知るとはぁ~メンドクサってなりませんか、あなた?

ブログ主が運営しているゲームです。

 MobileFight

 ジマさんの囲碁入門