phpでセッションの情報が消える
【概要】
- 現象
- PHPで書いた申請フォームで、ユーザIDによる認証を行っているが、時々申請者のメールアドレスが""@example.comとなることがある。
- 原因
- 入力に時間がかかりすぎたためにセッションがタイムアウトし、セッション情報(ここではユーザID)が削除されてしまっていた。
- 対策
- セッションの有効期限を長くする。
【セッションの有効期限とガーベッジ・コレクション】
- セッションの有効期限は、session.gc_maxlifetime パラメータで制御されている。デフォルトは24分。
- このパラメータは、セッション情報をサーバ上で残すべき時間を指定する
- これを超えると、消される「可能性」が生じる(必ず消えるとは限らない)
- セッション情報は、デフォルト(session.save_handler=files)ではファイルに格納されている
【セッションが消される契機(トリガー)】
- 同じAache+PHPのバイナリを共有する、いずれかのページ/アプリケーションに誰かがアクセスした時
- 問題が起きたのと同じアプリケーションとは限らない
- アクセスごとに毎回 GC をやらせるとシステムに負荷がかかるため、毎回 GC を行うかどうかの判定(確率計算)が行われる
【問題点】
- 現象
- 原因
- 同じホスト(かつ、同じセッション保持用ディレクトリ)を共有するすべての VirtualHost のうち一つでもこの設定がなされていないと、その設定していない VirtualHost にアクセスがあった場合、php.ini のデフォルト 値が有効となってしまうため。
【対策(1)】
- 対策
- 利点
- 簡単
- 欠点
【対策(2) - 公式マニュアルではこちらを推奨】
- 対策
- セッションの格納位置(session.save_path)の設定を、各 VirtualHost ごとに別々にする
- 利点
- VirtualHost間の相互影響範囲を限定できる
- 欠点
- あらかじめそれぞれのディレクトリを用意する必要がある
【備考】
- 多くのセッション情報(セッションファイル)の中でどのセッション情報を使うかは、クライアントが送りつけてくるクッキー(Set-cookie:ヘッダ)で決まる。
- たとえセッション情報の有効期限が session.gc_maxlifetime に達していなくても、クライアントがクッキーを送ってこない(もしくは別のクッキーを送って来た)場合、別セッション扱いとなり、セッション情報は引き継がれない。
- クライアントが(ブラウザで保持している)クッキーを送るかどうかは、以下のパラメータで決まる。
- session.cookie_lifetime : クッキーの有効期限(単位:秒、デフォルト180)
【参考資料】
以下のサイトを参考にさせていただきました:
セッションの有効期間とか設定とか挙動とかを調べました