PHP のセッションに関する覚え書き

PHP のセッションに関する基本事項やセキュリティなど

PHP でセッションを扱う場合に知っておくべき基本事項

自分でも忘れそうになるので、覚え書きとして書いておく。

セッションの維持期間

PHP のデフォルトの動作

  1. 有効期限は最終アクセスから 24分間 (1440秒)
  2. 有効期限が過ぎたセッションファイルは、 の確率で破棄される
  3. 有効期限内にセッションに再アクセスがあった場合は、期間は延長される

ちなみに、なぜ かと言うと。サーバーに負荷をかけないように、

「期限が切れたセッションファイルがある程度、溜まってから消す」

という理由によるもの。

セッションの維持期間を延ばす

セッションの有効期限を延ばす場合、例えば 1日 にしたい場合は ↓ こう

・プログラムに書く場合

ini_set( 'session.gc_maxlifetime', 86400 );  // 秒(デフォルト:1440)

プログラムにこれを書いても期限が延びないことがある
その場合は、セッションファイルの保存場所を変更しないとダメ。理由は後述。

・php.ini に書く場合

session.gc_maxlifetime = 86400

php.ini にこれを書くと全アプリケーションでセッション期限が伸びてしまうため注意。

ではなく確実に破棄したい場合

・プログラムに書く場合

ini_set( 'session.gc_probability', 1 );  // 分子(デフォルト:1)
ini_set( 'session.gc_divisor', 1 );  // 分母(デフォルト:100)

・php.ini に書く場合

session.gc_probability = 1
session.gc_divisor = 1

セッションファイルの保存場所

セッションファイルの保存場所は変更した方が良い。

理由:

  1. ホスティングなどの共有サーバーでは、他の人にセッションの内容を知られるかもしれない
  2. 複数のアプリケーションで同じ保存場所を使ってる場合、セッションの期間は一番小さい設定値に達した時点でデータが消去される

2. に関しては、PHP: 実行時設定 – session.gc_maxlifetime 参照

引用:

注意:
異なる値を session.gc_maxlifetime に指定している 別々のスクリプトがセッションデータの保存場所を共有している場合、 一番小さい設定値に達した時点でデータが消去されます。このような場合には、 お互いに session.save_path を使用します。

変更方法

・プログラムに書く場合

ini_set( 'session.save_path', 'ディレクトリ(フルパス)' );
もしくは
session_save_path( 'ディレクトリ(フルパス)' );

・php.ini に書く場合

session.save_path = "ディレクトリ(フルパス)"

クッキーの設定

クッキーでセッションを受け取る設定

セッションのクッキーを設定する場合のベストプラクティス | yohgaki's blog
に書かれてる通り。

引用:

  1. ドメイン名は指定しない
  2. パスはルート(/)を指定する
  3. セッション管理用のクッキーはセッションクッキー(有効期間 0)にする
  4. httponly属性を付ける
  5. 可能な場合は必ずsecure属性をつける
  6. 複数アプリケーションを利用する場合はsession.nameまたはsession_name()でセッションクッキー名で指定する (アプリケーションの固有名デフォルトで設定し、設定項目として変更できるようにする)

・プログラムに書く場合

短縮形
session_set_cookie_params( 0 );
ちゃんと全部書く場合
session_set_cookie_params( 0, '/', '', false, true );
secure な通信(SSL)の場合
session_set_cookie_params( 0, '/', '', true, true );

・php.ini に書く場合

session.cookie_lifetime = 0  #デフォルト 0 なので通常は不要
session.cookie_path = "/"  #デフォルト "/" なので通常不要
session.cookie_domain = ""  #デフォルト "" なので通常不要
session.cookie_secure = 1  #SSL通信(https://)な場合は付けた方が良い
session.cookie_httponly = 1

上記以外の設定

基本的にはクッキー以外ではセッションを受け取れないようにした方がセキュリティ上は良い。

・プログラムに書く場合

ini_set( 'session.use_cookies', 1 );  //デフォルト 1 なので通常は不要
ini_set( 'session.use_only_cookies', 1 );  //PHP5.3 以降はデフォルト 1、PHP5.2 以前は デフォルト 0
ini_set( 'session.use_trans_sid', 0 );  //デフォルト 0 なので通常は不要

・php.ini に書く場合

session.use_cookies = 1
session.use_only_cookies = 1
session.use_trans_sid = 0

どうしても、

  • $_GET
  • $_POST
  • $_SERVER['REQUEST_URI’]

等を使ってセッションを受け取りたい! っていう場合は ↓ こう

ini_set( 'session.use_only_cookies', 0 );
ini_set( 'session.use_trans_sid', 1 );
session.use_only_cookies = 0
session.use_trans_sid = 1

覚え書き

セッションクッキーの有効期間を 0 にした場合、session_destroy() しようが、有効期限を過去にして setcookie を送ろうが、(セッションは消えるが)クッキーはブラウザ終了まで消えない。
まぁ、どーでもいいw

その他のセキュリティ

新しいセッション ID への乗り換え

session_regenerate_id( true );

は、ほぼ必須。
session_regenerate_id はセッションの中身は維持したまま、セッションIDを 新しいものと置き換える関数。

パラメータに true をつけることで、古いセッションID は削除される。

必須ではあるが、ページ遷移するたびに新しい ID に乗り換えるとサーバーには負荷がかかる。
なので、ログイン直後にセッションID を乗り換えるだけで良い。

できれば、ログイン前はセッションを開始せず、ログイン直後にセッションを開始した方がより安全。

ログインしてるか否かの判定

  • ログインしてるかどうか
  • 自動ログインが有効化どうか

などの判定は、別セッション・クッキーにして、セッションの中身は true/false だけにしておけば良い。

特に、セッション管理用のクッキーは有効期間を 0 にすべきだが、
「自動ログインが有効化どうか」など判定は、クッキーの期限をある程度、長くする必要がある。
その場合は、別のクッキーに保存しなければならない。

クッキーの期限を延ばす方法は以下の通り。

・クッキーの寿命を一ヶ月にする場合

setcookie($name, $_COOKIE[$name], time() + time()+86400*30, '/', '', false, true);

↑ ただし、ログイン後のセッションに関するクッキーは、こーいう設定にしちゃダメ。

セッションの開始と破棄

session_start して、再度 session_start しちゃうとエラーになるので、
セッション開始する場合は、↓ とりあえずこう。

if( !isset( $_SESSION ) ) {
    session_start();
}

破棄する場合も ↓ こう

if( isset( $_SESSION ) ) {
    session_destroy();
}

乗り換える時も ↓ こう

if( isset( $_SESSION ) ) {
    session_regenerate_id( true );
}

基本以前に当たり前の話

セッションに関する ini_set や session_set_cookie_params は
session_start() を切る前に設定しないとダメ。当たり前。

参考

IT・ICT

Posted by るな