CXLII. セッション処理関数(session)

導入

PHPのセッションサポート機能は、複数回のアクセスを通じて特定のデー タを保持する手段を実現するものです。これにより、よりカスタマイズさ れたアプリケーションを構築し、自分の Web サイトのアピール度を増加 させることが可能となります。

Web サイトの訪問者にはセッションIDというセッションIDと呼ばれるユニークなIDが割りつけられ ます。このIDは、ユーザー側にクッキーとして保存するか、または、URL に埋め込みます。

セッションサポート機能により、任意の数の変数をリクエスト間で受けわたせる ようになります。来訪者がサイトにアクセスした際、 PHP は特定のセッションIDがリクエストとともに送信されているかどうかを ( session.auto_startが1の場合は)自動的に、または (session_start() により明示的な、あるいは session_register() により暗黙の) 要求を受けて確認します。 このIDが送信されている場合には、以前保存された変数が再現されます。

注意

session.auto_startをonとした場合、 オブジェクトをセッション変数に代入することができなくなります。 これは、セッションにおいてオブジェクトを再現するためには、 セッション開始前にクラス定義がロードされている必要があるためです。

全ての登録された変数は、リクエストが終了した後に、シリアル化されます。 未定義の登録変数は、未定義としてマーク付けされます。 これらの変数は、後でユーザーが定義しない限り、以降のアクセスにおいて セッションモジュールにより定義されません。

警告

いくつかのデータ型はシリアライズできませんので、 セッションにストアされません。これは resource 型の変数、 もしくは循環参照しているオブジェクト (例えば、 自分自身への参照を他のオブジェクトに渡しているオブジェクト) を含みます。

注意: セッション処理機能は、PHP 4.0 でサポートされました。

注意: セッションを処理している時、 session_register()関数を使用するか スーパーグローバル配列$_SESSIONへ新しいキーを 追加することにより変数が登録されるまで、セッションのレコードは作 成されないことに注意してください。これは、セッションが session_start()関数により開始されている場合で も真です。

セッションとセキュリティ

外部リンク: Session fixation

セッションモジュールは、セッションに保存した情報を見ることができる のがそのセッションを作成したユーザーだけであることを保証することが できません。セッションの完全性を積極的に守るには、そのセッションに 紐づく値に応じた追加措置が必要です。

セッションに運ばれるデータの重要性を評価し、必要な保護策を講じてください。 この対策は、通常は何らかの犠牲を伴うもので、ユーザの利便性を損なうことになります。 例えば、単純なソーシャルエンジニアリングからユーザを守るためには session.use_only_cookies を有効にする必要があります。 この場合、ユーザ側でクッキーが常に有効となっていなければならず、 有効でない場合はセッションが動作しなくなります。

存在するセッションIDが第三者に洩れる手順は何種類かあります。 洩れたセッションIDにより、第三者が特定のIDに関連する全てのリソー スにアクセスできるようになります。まず、セッションIDがURLにより伝 送される場合です。外部サイトにリンクを張っている場合、外部サイト のreferrerログにセッションIDを含むURLが保存される可能性があります。 第二に、よりアクティブな攻撃者がネットワークのトラフィックをモニ ターしている可能性があります。セッションIDが暗号化されていない場 合、セッションIDはネットワーク上を平文テキストで伝送されます。 解決策はサーバ上にSSLを実装し、ユーザにSSLを必ず使用させることです。

要件

外部ライブラリを必要としません。

注意: オプションで、Ralf S. Engelschallにより開発されたセッションの保 存用の共有メモリ(mm)を使用することも可能です。 mmをダウンロードし、インストールす ることができます。このオプションは、Windowsプラットフォームでは 利用できません。mm用セッション保存モジュールは同一セッションのロッ クに問題があるため、同時アクセスを保証することはできません。 ファイルにセッションを保存するためには、 (Solaris/LinuxまたはBSD上の/dev/md)ファイルシステムに 共有メモリを使用するためにより適当でしょう。 セッションのデータはメモリに保存されます。そのため、Web サーバを 再起動するとデータが削除されます。

インストール手順

PHPのセッションサポートはデフォルトで有効となっています セッションサポートを有効にしてPHPを構築したくない場合には、 configureにオプション--disable-sessionを指定する必要があります。 セッション記憶領域として共有メモリ(mm)を使用するには、PHPのconfigure に--with-mm[=DIR]を指定します。

Windows 版の PHP には この拡張モジュールのサポートが組み込まれています。これらの関数を使用 するために拡張モジュールを追加でロードする必要はありません。

注意: デフォルトでは、特定のセッションのすべての情報は session.save_path INIオプションで指定されたディレクトリに生成される ファイルに保存されます。 結びついている情報に関わらずセッション毎にひとつのファイルが生成されます。 セッションが開始され(ファイルが生成される)しかし何の情報も そのファイルに書き込まれない場合もあります(サイズがゼロのファイルが残る)。 この振る舞いはファイルシステムを使っていることによる副作用であり、 カスタムセッションハンドラ(例:データベースを使ったもの)を 使う場合には何の情報も持たないセッションについて追跡しないように することは可能です。

実行時設定

php.ini の設定により動作が変化します。

表 1. セッションの設定オプション

名前デフォルト変更の可否変更履歴
session.save_path""PHP_INI_ALL 
session.name"PHPSESSID"PHP_INI_ALL 
session.save_handler"files"PHP_INI_ALL 
session.auto_start"0"PHP_INI_ALL 
session.gc_probability"1"PHP_INI_ALL 
session.gc_divisor"100"PHP_INI_ALLPHP 4.3.2 から利用可能
session.gc_maxlifetime"1440"PHP_INI_ALL 
session.serialize_handler"php"PHP_INI_ALL 
session.cookie_lifetime"0"PHP_INI_ALL 
session.cookie_path"/"PHP_INI_ALL 
session.cookie_domain""PHP_INI_ALL 
session.cookie_secure""PHP_INI_ALLPHP 4.0.4 から利用可能
session.cookie_httponly""PHP_INI_ALLPHP 5.2.0 から使用可能
session.use_cookies"1"PHP_INI_ALL 
session.use_only_cookies"1"PHP_INI_ALLPHP 4.3.0 から利用可能
session.referer_check""PHP_INI_ALL 
session.entropy_file""PHP_INI_ALL 
session.entropy_length"0"PHP_INI_ALL 
session.cache_limiter"nocache"PHP_INI_ALL 
session.cache_expire"180"PHP_INI_ALL 
session.use_trans_sid"0"PHP_INI_ALLPHP_INI_ALL は PHP <= 4.2.3、PHP_INI_PERDIR は PHP < 5 から。PHP 4.0.3 から利用可能。
session.bug_compat_42"1"PHP_INI_ALLPHP 4.3.0 から利用可能
session.bug_compat_warn"1"PHP_INI_ALLPHP 4.3.0 から利用可能
session.hash_function"0"PHP_INI_ALLPHP 5.0.0 から利用可能
session.hash_bits_per_character"4"PHP_INI_ALLPHP 5.0.0 から利用可能
url_rewriter.tags"a=href,area=href,frame=src,form=,fieldset="PHP_INI_ALLPHP 4.0.4 から利用可能
PHP_INI_* 定数の詳細および定義については 付録G を参照してください。

セッション管理システムは、php.iniファイルに記述可能な多くの設定オ プションをサポートします。以下に概要を示します。

session.save_handler string

session.save_handler は、セッションに関連す るデータの保存および取得に使用されるハンドル名を定義します。デ フォルトは、filesです。 session_set_save_handler()も参照してください。

session.save_path string

session.save_path は、保存ハンドラに渡される 引数を定義します。デフォルトのファイルハンドラを選択した場合、 ファイルが作成される場所のパスになります。デフォルトは、 /tmp です。 session.save_pathのパスの深さが2より大きい場 合、ガーベッジコレクションは行われません。 session_save_path()も参照してください。

オプションの引数としてN(数値)を指定できます。 これはセッションファイルを分散して保存する際に ディレクトリ階層レベルを決定します。 例えば、'5;/tmp'とすると /tmp/4/b/1/e/3/sess_4b1e384ad74619bd212e236e52a5a174If という位置にセッションファイルを生成します。 Nを使用するには、これらすべてのディレクトリが 事前に作成されている必要があります。 そのためのシェルスクリプトがext/sessionmod_files.shというファイル名であります。 また、0以上のNが指定されている場合には自動ガーベッジコレクション が機能しないことに注意してください。詳細は php.ini を見てください。 また、Nを指定する場合は、 session.save_pathを"quotes"で囲う必要があります。 なぜならセパレータ(;) は php.ini ではコメントとしても利用されているからです。

警告

この設定を/tmp (デフォルト)のようにどこか らでも読み込み可能なディレクトリのままにしている場合、サーバ上 の他のユーザがこのディレクトリのファイルのリストを取得すること により、セッションをハイジャックをすることが可能となります。

注意: PHP 4.3.6 以前では、WindowsユーザがPHPのsession関数を使用するためには、 この変数を変更する必要があります。c:/temp のような有効なパスを指定するようにしてください。

session.name string

session.name はセッション名を指定し、 クッキー名として使用されます。 アルファベット文字のみで指定する必要があります。 デフォルトは、PHPSESSID です。 session_name()も参照してください。

session.auto_start boolean

session.auto_start はリクエスト開始時に セッションモジュールがセッションを自動的に開始するかどうかを 指定します。デフォルトは、0(無効)です。

session.serialize_handler string

session.serialize_handler は、シリアル化または シリアル化データを復元するために使用されるハンドラの名前を 定義します。現在、( php という名前の) PHP 内部 フォーマットおよび (wddx という名前の) WDDX が サポートされています。WDDX は、PHP がWDDX サポート を有効にしてコンパイル されている場合のみ使用可能です。デフォルトは、 php です。

session.gc_probability integer

session.gc_probabilitysession.gc_divisorの組み合わせでgc (ガーベッジコレクション)ルーチンの始動を制御します。 デフォルトは、1 です。 詳細はsession.gc_divisor をご覧ください

session.gc_divisor integer

session.gc_divisorsession.gc_probabilityの組み合わせで すべてのセッションの初期化過程でgc(ガーベッジコネクション)プロセス も始動する確率を制御します。確率は gc_probability/gc_divisor で計算されます。例えば、1/100は各リクエスト毎に1%の確率でGCプロセスが 始動します。 session.gc_divisorのデフォルトは100です。

session.gc_maxlifetime integer

session.gc_maxlifetime は、データが 'ごみ' とみなされ、消去されるまでの秒数を指定します。 ガベージコレクション (ごみの収集) は、 セッションの開始時に行われます。

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

注意: デフォルトのファイルに基づくセッションハンドラを使用している場 合、使用するファイルシステムは、アクセス時間(atime)を記録できる 必要があります。Windows FATはこれができないため、 FATファイルシステムまたはatimeの記録ができない他のファイルシス テムで問題を発生した場合は、セッションのガベージコレクト処理を 行う他の手段を用意する必要があります。 PHP4.2.3以降、atimeの代わりにmtime(更新時刻)が使用されます。 このため、atimeが利用できないファイルシステムでの問題は無くなりました。

session.referer_check string

session.referer_check には、HTTP Referer に おいて確認を行う文字列を指定します。Refererがクライアントにより 送信されており、かつ、指定した文字列が見付からない場合、埋め込 まれたセッションIDは無効となります。デフォルトは空の文字列です。

session.entropy_file string

session.entropy_file は、 セッションIDを作成する際の別のエントロピソースとして使用する 外部リソースへのパスを指定します。 例としては、多くの UNIX で利用可能な /dev/random または /dev/urandom があげられます。

session.entropy_length integer

session.entropy_length は、前記のファイルから 読みこむバイト数を指定します。デフォルトは、0 (無効)です。

session.use_cookies boolean

session.use_cookiesによりクライアント側にセッ ションIDを保存する際にクッキーを使用するかどうかを指定します。デ フォルトは1 (有効)です。

session.use_only_cookies boolean

session.use_only_cookies は、 このモジュールがクライアント側へのセッション ID の保存に Cookie のみ を使用することを指定します。 この設定を有効にすることにより、セッション ID を URL に埋め込む攻撃を防ぐことができます。この設定は、 PHP 4.3.0 で追加されました。

session.cookie_lifetime integer

session.cookie_lifetime は、 ブラウザに送信するクッキーの有効期間を秒単位で指定します。 0 を指定すると "ブラウザを閉じるまで" という意味になります。 デフォルトは、0 です。 session_get_cookie_params() および session_set_cookie_params() も参照してください。 クッキーはブラウザから返されるので、 有効期間を満たすまで長引かせることはできません。 setcookie() を用いて手動で送信しなければなりません。

session.cookie_path string

session.cookie_pathによりsession_cookieで設 定するパスを指定します。デフォルトは/です。 session_get_cookie_params()および session_set_cookie_params()も参照してください。

session.cookie_domain string

session.cookie_domain により session_cookie で 指定するドメインを指定します。デフォルトでは指定されません。 この場合は、クッキーの仕様によって、クッキーを作成したサーバの ホスト名が指定されます。 session_get_cookie_params() および session_set_cookie_params() も参照ください。

session.cookie_secure boolean

session.cookie_secureは、 セキュアな接続を通じてのみCookieを送信できるかどうかを指定します。 デフォルトは、offです。 この設定は、PHP 4.0.4で追加されました。 session_get_cookie_params()および session_set_cookie_params()も参照してください。

session.cookie_httponly boolean

クッキーに対して、HTTP を通してのみアクセスできるようにします。 つまり、JavaScript のようなスクリプト言語からはアクセスできなくなるということです。 この設定を使用すると、XSS 攻撃によって ID を盗まれる危険性を減らせます (が、すべてのブラウザがこの設定をサポートしているというわけではありません)。

session.cache_limiter string

session.cache_limiterにより セッションページにおけるキャッシュ制御の方法 (none/nocache/private/private_no_expire/public) を指定します。デフォルトは、nocacheです。 session_cache_limiter()も参照してください。

session.cache_expire integer

session.cache_expireによりキャッシュされた セッションページの有効期間を分単位で指定します。 このオプションは、nocacheリミッタに関しては効果がありません。 デフォルトは、180です。 session_cache_expire()も参照してください。

session.use_trans_sid boolean

session.use_trans_sidは、透過的なセッション IDの付加をするかどうかを指定します。 デフォルトは、0(無効)です。

注意: PHP 4.1.2より前のバージョンでは、このオプションは --enable-trans-sidにより コンパイル時に有効とされていました。 PHP 4.2.0以降、trans-sid機能は常にコンパイルされます。

URLに基づくセッション管理は、Cookieに基づくセッション管理と比べ てセキュリティリスクが大きくなります。例えば、ユーザは、emailに より友人にアクティブなセッションIDを含むURLを送信する可能性があ り、また、ユーザは自分のブックマークにセッションIDを含むURLを保 存し、常に同じセッションIDで使用するサイトにアクセスする可能性 があります。

session.bug_compat_42 boolean

PHP バージョンが 4.2.3 とそれ以前には、たとえ register_globals が無効の場合でもグローバルスコープでセッション変数の初期化を 許してしまうドキュメント化されていない特徴/バグがあります。 この機能を使用している場合で session.bug_compat_warn も有効にしている場合、 PHP 4.3.0 とそれ以降のバージョンでは警告が発されます。 この特徴/バグは、 このディレクティブを無効にすることで無効にすることが可能です。

session.bug_compat_warn boolean

PHP バージョンが 4.2.3 とそれ以前には、たとえ register_globals が無効の場合でもグローバルスコープでセッション変数の初期化を 許してしまうドキュメント化されていない特徴/バグがあります。 この機能を session.bug_compat_42 session.bug_compat_warn を有効にして使用している場合、 PHP 4.3.0 とそれ以降のバージョンでは警告が発されます。

session.hash_function integer

session.hash_function によりセッション ID を生成するために使用されるハッシュアルゴリズムを指定することが可能です。 '0' は MD5 (128 ビット) で、'1' は SHA-1 (160 ビット) を意味します。

注意: このディレクティブは PHP 5 で導入されました。

session.hash_bits_per_character integer

session.hash_bits_per_character により バイナリのハッシュデータを何らかの可読なデータに変換する際、 それぞれの文字に何ビットストアさせるかを定義することが可能です。 指定可能な値は、'4' (0-9, a-f)、'5' (0-9, a-v) そして '6' (0-9, a-z, A-Z, "-", ",") です。

注意: このディレクティブは PHP 5 で導入されました。

url_rewriter.tags string

url_rewriter.tagsは、透過的なセッションIDの 付加機能が有効となった場合に、セッションIDを含めるために書き換 えられるHTMLタグを指定します。デフォルトは、 a=href,area=href,frame=src,input=src,form=fakeentry,fieldset= です。

注意: XHTML に適合させたい場合には form エントリは削除し、 formフィールドの前後に<fieldset> タグを使ってください。

track_varsおよび register_globals 設定はセッション変数の保存および回復方法に影響を与えます。

注意: PHP 4.0.3以降、track_vars は常 にonとなっています。

リソース型

リソース型は定義されていません。

定義済み定数

以下の定数が定義されています。 この関数の拡張モジュールが PHP 組み込みでコンパイルされているか、 実行時に動的にロードされている場合のみ使用可能です。

SID (string)

"name=ID"形式でセッション名とセッションIDを格納している定数。 セッションIDがセッションクッキーに適切にセットされている場合には空文字列が入る。

注意: PHP 4.1.0以降、$_SESSIONは、 $_POST, $_GET, $_REQUEST等のようにグローバル変数として利用可 能です。$HTTP_SESSION_VARSと異なり、 $_SESSIONは常にグローバルです。そこで、 global$_SESSIONの場合は不要です。 このドキュメントでは、$_SESSION をあらゆる場 所で使用していることに注意してください。もし前者を使用したい場合に は、$_SESSION$HTTP_SESSION_VARSで置き換えることができます。 また、$_SESSIONを使用する前に session_start() を用いてセッションを開始して おく必要があることに注意してください。

連想配列$_SESSIONのキーは、PHPの通常の変数名 と同じ制限があります。すなわち、数字で始まることはできず、文字ま たはアンダースコアで始まる必要があります。 詳細については、本マニュアルの 変数の節を参照して下さ い。

register_globals が無効の場合、グローバル連想配列$_SESSIONのメ ンバーのみがセッション変数として登録されます。 回復されたセッション変数は、配列$_SESSIONでの み利用可能です。

セキュリティとコードの可読性のために$_SESSION (またはPHP 4.0.6以前は$HTTP_SESSION_VARS)の使用 が推奨されます。$_SESSIONの場合、 session_register(), session_unregister(), session_is_registered()は不要です。ユーザは、 通常の変数と同様にセッション変数にアクセス可能 です。

例 1. $_SESSIONで変数を登録

<?php
session_start
();
// PHP 4.0.6以前の場合は$HTTP_SESSION_VARSを使用してください
if (!isset($_SESSION['count'])) {
    
$_SESSION['count'] = 0;
} else {
    
$_SESSION['count']++;
}
?>

例 2. register_globals が無効な場合に、$_SESSIONに登録されている変 数の登録を解除する

<?php
session_start
();
// PHP 4.0.6とそれ以前では$HTTP_SESSION_VARSを使用してください
unset($_SESSION['count']);
?>

注意

unset($_SESSION)によって 全ての$_SESSIONを初期化してはいけません。 $_SESSIONスーパーグローバル変数を用いた セッション変数の登録ができなくなってしまうからです。

警告

セッション変数において参照を使用することはできません。 他の変数への参照の再現する方法がないからです。

register_globals が有効な場合、全てのグローバル変数はセッション変数として登録するこ とが可能で、セッション変数は対応するグローバル変数として回復されま す。PHPは、どのグローバル変数がセッション変数として登録されるのか を知る必要があるため、ユーザは、変数を session_register()関数で登録する必要がありま す。しかし、$_SESSIONの場合は、エントリを設定 するだけでこれを行う必要はありません。

注意

$_SESSIONを使用し、register_globals を無効とする場合、自分のスクリプトをPHP 4.2より以前のバージョン で動作させたい場合は、 session_register(), session_is_registered(), session_unregister()を使用しないでください。 PHP 4.3以降ではこれらの関数を使用することができます。 セキュリティ面と性能面の双方よりregister_globals を無効とすることが推奨されています。

register_globals が有効な場合、グローバル変数と$_SESSIONの エントリは、前のセッションインスタンスで登録されたセッション変数 の同じ値を参照することになります。 しかし、変数が $_SESSION で登録された場合、 グローバル変数が使用可能となるのは次のリクエスト以降です。

PHP 4.2.3とそれ以前のバージョンのみに関係する問題があります。 session_register()により新しいセッショ ン変数を登録する場合、グローバルスコープのエントリと $_SESSIONのエントリは、次の session_start()まで同じ値へのリファレンスとは なりません。 すなわち、グローバル変数への修正は、$_SESSION のエントリには反映されません。PHP 4.3では修正されています。

セッションIDの受渡し

セッションIDの通知を行うためには次の二つの方法があります。

  • Cookie

  • URLパラメータ

sessionモジュールは、両方の方法をサポートします。 Cookieは最適ですが、(クライアントがCookieを受け入れない可能性が あるため)信頼性がなく、これに依存することができません。2番目の方 法は、セッションIDを直接URLに埋め込みます。

PHPには、透過的にリンクを変換する機能を有しています。 PHP 4.2以降を使用していない場合、PHP構築時にこの機能を有効にして おく必要があります。UNIX環境では、 --enable-trans-sidをconfigureに指定して ください。この構築オプションと実行時オプション session.use_trans_sidが有効な場合、 相対URIは自動的にセッションIDを含むように変換されます。

注意: arg_separator.output php.ini ディレクティブにより、引数セパレータをカスタマイズする ことができます。XHTMLに完全準拠するためには、ここに &amp; を指定してください。

もしくは、セッションが開始している場合に定義されている定数 SID を使用することもできます。クライアントが適当な セッションクッキーを送信しなかった場合、この定数は session_name=session_id の形式となります。 他方、送信された場合には、この定数は空の文字列に展開されます。 このため、この定数を無条件に URL に埋め込むことができます。

次の例は、変数の登録法および SID を用いて他のページに正しくリンク する方法のデモです。

例 3. 単一のユーザーに関するヒット数を数える

<?php
if (!session_is_registered('count')) {
    
session_register('count');
    
$count = 1;
} else {
    
$count++;
}
?>

<p>
こんにちは、あなたがこのページに来たのは<?php echo $count; ?>回目ですね。
</p>

<p>
続けるには、<A HREF="nextpage.php?<?php echo strip_tags (SID)?>">ここをクリック</A>
してください。
</p>

XSSに関係する攻撃を防止するためにSIDを出力する際に、 strip_tags()を使用します。

PHPをコンパイルする際に --enable-trans-sid を使用した場合、 上の例のように SID を出力する必要はありません。

注意: 相対URLでないURLは外部サイトを指していると仮定され、SIDが追加 されません。これは、SIDを外部のサーバに開示することはセキュリティ 上のリスクとなる可能性があるためです。

カスタムセッションハンドラ

セッション情報をデータベースに保存する機能か他の保存法を実装する には、一連のユーザレベルの保存関数を作成し、 session_set_save_handler()を使用する必要があり ます。

目次
session_cache_expire -- カレントのキャッシュの有効期限を返す
session_cache_limiter -- カレントのキャッシュリミッタを取得または設定する
session_commit -- session_write_close() のエイリアス
session_decode -- 文字列からセッションデータをデコードする
session_destroy -- セッションに登録されたデータを全て破棄する
session_encode --  現在のセッションデータを文字列としてエンコードする
session_get_cookie_params --  セッションクッキーのパラメータを得る
session_id -- カレントのセッション ID を取得または設定する
session_is_registered --  変数がセッションに登録されているかどうかを調べる
session_module_name -- 現在のセッションモジュールを取得または設定する
session_name -- カレントのセッション名を取得または設定する
session_regenerate_id --  現在のセッションIDを新しく生成したものと置き換える
session_register -- 現在のセッションに1つ以上の変数を登録する
session_save_path --  現在のセッションデータ保存パスを取得または設定する
session_set_cookie_params --  セッションクッキーパラメータを設定する
session_set_save_handler --  ユーザ定義のセッション保存関数を設定する
session_start -- セッションデータを初期化する
session_unregister -- 現在のセッションから変数の登録を削除する
session_unset --  全てのセッション変数を開放する
session_write_close -- セッションデータを書き込んでセッションを終了する