セッションの有効期間(1/2)
PHPにおけるセッションの有効期間とCakePHPにおけるそれと別々にきちんと理解しないと一体いつまでセッションが有効なのかわからないので、ちょっとまとめてみることにする。
PHPのセッション有効期間
表面的に関係するのは cookie_lifetime と gc_maxlifetime の2つのパラメータとなる。
まぁ今更説明するまでもないが、セッションはクッキーでランダムな英数字(セッションID)をやりとりして、サーバ側でセッションID毎にデータを確保するというものだ。PHPの場合デフォルトだとファイルにデータを確保することになっている。
つまり、クライアントがクッキーを送るのはいつまでか、サーバがセッションデータをいつまで保持するのか、を把握すれば、いつまでセッションが有効なのかを理解できる。
=====クライアントがクッキーを送るのはいつまでか=====
cookie_lifetime というパラメータで設定できるようになっていて、デフォルトは 0 となっている。0 というのはブラウザを終了させるまでずっと、という意味で、PHPは expires 無しの Set-Cookie パラメータを出力します。こんなカンジです。
Set-Cookie: PHPSESSID=btnvj6ppsstj09jdt3j3dkdre2; path=/
この設定の場合、例えばどこかのページにアクセスして、ブラウザを終了させずに30分放置してから再度アクセスした場合もブラウザはこのセッションIDを送ろうとします。なので、10分経ったらセッションIDを送ってこないようにしたい場合は
cookie_lifetime = 600
とします(秒数で指定)。そうすると、PHPはこんなSet-Cookieを出力します。
Set-Cookie: PHPSESSID=0orcis03aaluitusgiubha3l03; expires=Wed, 29-Aug-2011 01:09:38 GMT; path=/
これで安心かと思いきや、これはこれで2つ問題があります。
1つは、最終アクセスではなく初回アクセスから10分後まで、となってしまう点です。本当は最後にアクセスしてから10分以内はセッション有効としたいところですが、そうはなってくれません。
あと1つは、クッキーを送るか送らないかはブラウザ側の仕様によりけりなので、いくらこっちが10分後までと指定してもそれを律儀に守ってくれるかどうかはわからないところです。
なので結局 cookie_lifetime = 0 でいいと思います。
=====サーバでセッションデータファイルをいつまで保管するのか=====
今度はサーバ側のパラメータ gc_maxlifetime のお話。gc というのは「ガベージコレクション」(ゴミ掃除)という意味で、セッションデータのゴミ掃除をする際に、どれぐらい古いデータをゴミとみなすかを設定します。
例えば30分セッションデータの更新が無ければゴミとしたいなら、
gc_maxlifetime = 1800
とします(秒数で指定)。これで30分以上アクセスが無かったら、いくらセッションクッキーを送ってきてもセッションデータファイルが無いのでセッションが無効になります。
と思ったら大間違いです!
これはあくまでセッションデータファイルを掃除するタイミングで、セッションデータが有効かどうかを指定するパラメータではありません。何を言ってるのか「?」だと思いますのでさらに詳しい説明を。
例えばあるページにアクセスしてセッションが開始されます。その後ブラウザを1時間放置してから再度アクセスします(他のユーザは誰もアクセスしていなかったとする)。すると、30分以上経過していますが、セッションは有効です。どうしてかというと、セッションデータファイルが残っているからです。
セッションデータファイルの削除は、いくら gc_maxlifetime を超えても他のユーザのアクセスが無いとゴミ掃除は発動しないのです。じゃー、30分経過してから他のユーザがアクセスしたら必ず消されるのかというと、そうでもないのです。
ここで2つのパラメータgc_probabilityとgc_divisorが出てきます。これらはセッションデータファイルを削除する確率を指定するパラメータで、アクセスがある度に、gc-probability/gc_divisor の確率でセッションデータファイルを削除します。簡単に言うと、probability = gc_divisor = 1 なら、毎アクセスセッションデータファイルを削除しようとします。ただそれだと余計な処理に時間が使われることになります。(デフォルトは gc_divisor = 100 なので、100アクセスに1回の割合)
結論として、PHPのセッション機能単体だと厳密に指定した時間でセッション管理できないのです。ま、PHPにそんな厳密さを求めるのがそもそも間違い!(笑)