読者です 読者をやめる 読者になる 読者になる

バカンス駆動開発

この前バカンスって言ったら「古っ」って言われました

PHPのsessionファイルの生成場所、中身、有効期限など

php

PHPでセッションを開始すると$_SESSIONに値を出し入れできますが実態はsessionファイルに物理的に書き込まれています。*1
中身見たことなかったのでちょっと調べました。

sessionファイルの場所

生成場所の優先順位

  1. php.iniのsession.save_path
  2. php.iniのsys_temp_dir
  3. /tmpとか

sess_v4vqefhjjllja1bqsabekihpc4みたいな感じでsess_xxxxxxxxxxxxxxという名前のファイル名で保存されます。

sessionファイルの中身

試しにこれを実行すると

<?php
session_start();
$_SESSION['hoge'] = 'hoge';
$_SESSION['huga'] = 'huga';

自分の環境だと/tmp/sess_v4vqefhjjllja1bqsabekihpc4が生成されました。中身をみると

cat /tmp/sess_v4vqefhjjllja1bqsabekihpc4

// 結果
hoge|s:4:"hoge";huga|s:4:"huga";

ぱっと見配列をserialize()したものっぽいですが微妙に違います。
session_encodeという関数を使ってエンコードしているようです。
PHP: session_encode - Manual

デフォルトのアンシリアライズの方法は PHP が内部的に実装しているものであり、 unserialize() とは違います。 シリアライズの方法は、session.serialize_handler で設定できます。

phpinfoを確認するとsession.serialize_handlerにはphpと設定されていました。これがデフォルト値です。試しにphp_serializeに変えてphpを再起動してsessionファイルを確認してみると

cat /tmp/sess_v4vqefhjjllja1bqsabekihpc4

// 結果
a:2:{s:4:"hoge";s:4:"hoge";s:4:"huga";s:4:"huga";}

とまぁおなじみのシリアライズされた文字列になりました。ハンドラがデフォルトのphpだと$_SESSIONの中で数値のインデックスや特殊文字 (| や !) を含む文字列のインデックスが使えません。

sessionファイル名とセッションID

リクエストヘッダーを見るとv4vqefhjjllja1bqsabekihpc4というセッションIDを送っています。

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch
Accept-Language:ja,en-US;q=0.8,en;q=0.6,de;q=0.4,fr;q=0.2,ko;q=0.2
Cache-Control:max-age=0
Connection:keep-alive
Cookie:PHPSESSID=v4vqefhjjllja1bqsabekihpc4 // ←!
Host:local.example.com
Upgrade-Insecure-Requests:1

クライアントから送信されたセッションIDとsessionファイルの関連付けをどうやっているのかというとそのままセッションIDに接頭辞としてsess_をつけているだけだけでした。セッションIDをそのままファイル名に使っているというのはなにやら不安な気持ちになりますね。

session_regenerate_id ()を実行するとセッションIDが新しく変わるので新しいsess_xxxxxxが生成され、クライアントに新しいセッションIDを返します。

有効期限

セッションスタート時にgcが走ります。
sessionファイルのうち生成からsession.gc_maxlifetime秒経っているファイルが対象で、session.gc_divisor分のsession.gc_probabilityの確率で削除が実行されます。

*1:デフォルトでは。