Another way of handling the "www" versus non-"www" URL's:
In your .htaccess file, add:
RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_HOST} ^www.yourdomain.com$
RewriteRule ^(.*)$ http://yourdomain.com/$1 [R=301,L]
This will rewrite:
www.yourdomain.com/anything
to:
yourdomain.com/anything
To reverse, e.g. add a www if it isn't present, change the 3rd line to:
RewriteCond %{HTTP_HOST} !^www.yourdomain.com$
セッション処理関数(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.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 の設定により動作が変化します。
| 名前 | デフォルト | 変更の可否 | 変更履歴 |
|---|---|---|---|
| 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_ALL | PHP 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_ALL | PHP 4.0.4 から利用可能 |
| session.cookie_httponly | "" | PHP_INI_ALL | PHP 5.2.0 から使用可能 |
| session.use_cookies | "1" | PHP_INI_ALL | |
| session.use_only_cookies | "1" | PHP_INI_ALL | PHP 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_ALL | PHP_INI_ALL は PHP <= 4.2.3、PHP_INI_PERDIR は PHP < 5 から。PHP 4.0.3 から利用可能。 |
| session.bug_compat_42 | "1" | PHP_INI_ALL | PHP 4.3.0 から利用可能。PHP 6.0.0 で削除。 |
| session.bug_compat_warn | "1" | PHP_INI_ALL | PHP 4.3.0 から利用可能。PHP 6.0.0 で削除。 |
| session.hash_function | "0" | PHP_INI_ALL | PHP 5.0.0 から利用可能 |
| session.hash_bits_per_character | "4" | PHP_INI_ALL | PHP 5.0.0 から利用可能 |
| url_rewriter.tags | "a=href,area=href,frame=src,form=,fieldset=" | PHP_INI_ALL | PHP 4.0.4 から利用可能 |
セッション管理システムは、php.iniファイルに記述可能な多くの設定オ プションをサポートします。以下に概要を示します。
- session.save_handler string
- session.save_handler は、 セッションに関連するデータの保存および取得時に使用するハンドラを定義します。 デフォルトは、files です。各拡張モジュールで、 独自の save_handler を使用できることに注意しましょう。 インストール環境単位で登録されているハンドラを取得するには phpinfo() を使用します。 session_set_save_handler() も参照してください。
- session.save_path string
-
session.save_path は、保存ハンドラに渡される
引数を定義します。デフォルトのファイルハンドラを選択した場合、
ファイルが作成される場所のパスになります。
session_save_path() も参照ください。
オプションの引数としてN(数値)を指定できます。 これはセッションファイルを分散して保存する際に ディレクトリ階層レベルを決定します。 例えば、'5;/tmp'とすると /tmp/4/b/1/e/3/sess_4b1e384ad74619bd212e236e52a5a174If という位置にセッションファイルを生成します。 Nを使用するには、これらすべてのディレクトリが 事前に作成されている必要があります。 そのためのシェルスクリプトがext/sessionに mod_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_binary という名前の) PHP 内部フォーマットおよび (wddx という名前の) WDDX がサポートされています。WDDX は、PHP がWDDX サポート を有効にしてコンパイルされている場合のみ使用可能です。デフォルトは、 php です。
- session.gc_probability integer
- session.gc_probabilityと session.gc_divisorの組み合わせでgc (ガーベッジコレクション)ルーチンの始動を制御します。 デフォルトは、1 です。 詳細はsession.gc_divisor をご覧ください
- session.gc_divisor integer
- session.gc_divisorと session.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によりクライアント側にセッ ションIDを保存する際にクッキーを使用するかどうかを指定します。デ フォルトは1 (有効)です。
- session.use_only_cookies は、 このモジュールがクライアント側へのセッション ID の保存に Cookie のみ を使用することを指定します。 この設定を有効にすることにより、セッション ID を URL に埋め込む攻撃を防ぐことができます。この設定は、 PHP 4.3.0 で追加されました。 PHP 6.0 以降で、デフォルトは 1 (有効) となります。
-
session.cookie_lifetime は、
ブラウザに送信するクッキーの有効期間を秒単位で指定します。
0 を指定すると "ブラウザを閉じるまで" という意味になります。
デフォルトは、0 です。
session_get_cookie_params() および
session_set_cookie_params() も参照してください。
注意: 有効期限のタイムスタンプは、サーバの時刻に基づいて決まります。 クライアントのブラウザの時刻がこれと同じであるとは限りません。
- session.cookie_pathによりsession_cookieで設 定するパスを指定します。デフォルトは/です。 session_get_cookie_params()および session_set_cookie_params()も参照してください。
- session.cookie_domain により session_cookie で 指定するドメインを指定します。デフォルトでは指定されません。 この場合は、クッキーの仕様によって、クッキーを作成したサーバの ホスト名が指定されます。 session_get_cookie_params() および session_set_cookie_params() も参照ください。
- session.cookie_secureは、 セキュアな接続を通じてのみCookieを送信できるかどうかを指定します。 デフォルトは、offです。 この設定は、PHP 4.0.4で追加されました。 session_get_cookie_params()および session_set_cookie_params()も参照してください。
- クッキーに対して、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 mixed
-
session.hash_function によりセッション ID
を生成するために使用されるハッシュアルゴリズムを指定することが可能です。
'0' は MD5 (128 ビット) で、'1' は SHA-1 (160 ビット) を意味します。
PHP 6.0.0 以降では、hash 拡張モジュール の任意のアルゴリズムが (この拡張モジュールが使用可能な場合に) 指定できるようになります。たとえば sha512 や whirlpool などです。 サポートされているアルゴリズムの一覧は、 hash_algos() 関数で取得できます。
注意: このディレクティブは 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は、透過的なセッションIDの
付加機能が有効となった場合に、セッションIDを含めるために書き換
えられるHTMLタグを指定します。デフォルトは、
a=href,area=href,frame=src,input=src,form=fakeentry,fieldset=
です。
注意: HTML/XHTML strict に適合させたい場合には 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()は不要です。ユーザは、 通常の変数と同様にセッション変数にアクセス可能 です。
Example#1 $_SESSIONで変数を登録
<?php
session_start();
// PHP 4.0.6以前の場合は$HTTP_SESSION_VARSを使用してください
if (!isset($_SESSION['count'])) {
$_SESSION['count'] = 0;
} else {
$_SESSION['count']++;
}
?>
Example#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.0 以降ではこれらの関数を使用することができます。 セキュリティ面と性能面の双方よりregister_globals を無効とすることが推奨されています。
register_globals が有効な場合、グローバル変数と$_SESSIONの エントリは、前のセッションインスタンスで登録されたセッション変数 の同じ値を参照することになります。 しかし、変数が $_SESSION で登録された場合、 グローバル変数が使用可能となるのは次のリクエスト以降です。
PHP 4.2.3とそれ以前のバージョンのみに関係する問題があります。 session_register()により新しいセッショ ン変数を登録する場合、グローバルスコープのエントリと $_SESSIONのエントリは、次の session_start()まで同じ値へのリファレンスとは なりません。 すなわち、グローバル変数への修正は、$_SESSION のエントリには反映されません。PHP 4.3.0 では修正されています。
セッションIDの受渡し
セッションIDの通知を行うためには次の二つの方法があります。
- Cookie
- URLパラメータ
sessionモジュールは、両方の方法をサポートします。 Cookieは最適ですが、(クライアントがCookieを受け入れない可能性が あるため)信頼性がなく、これに依存することができません。2番目の方 法は、セッションIDを直接URLに埋め込みます。
PHPには、透過的にリンクを変換する機能を有しています。 PHP 4.2.0 以降を使用していない場合、PHP構築時にこの機能を有効にして おく必要があります。UNIX環境では、 --enable-trans-sidをconfigureに指定して ください。この構築オプションと実行時オプション session.use_trans_sidが有効な場合、 相対URIは自動的にセッションIDを含むように変換されます。
注意: arg_separator.output php.ini ディレクティブにより、引数セパレータをカスタマイズする ことができます。XHTMLに完全準拠するためには、ここに & を指定してください。
もしくは、セッションが開始している場合に定義されている定数 SID を使用することもできます。クライアントが適当な セッションクッキーを送信しなかった場合、この定数は session_name=session_id の形式となります。 他方、送信された場合には、この定数は空の文字列に展開されます。 このため、この定数を無条件に URL に埋め込むことができます。
次の例は、変数の登録法および SID を用いて他のページに正しくリンク する方法のデモです。
Example#3 単一のユーザーに関するヒット数を数える
<?php
session_start();
if (empty($_SESSION['count'])) {
$_SESSION['count'] = 1;
} else {
$_SESSION['count']++;
}
?>
<p>
こんにちは、あなたがこのページに来たのは <?php echo $_SESSION['count']; ?> 回目ですね。
</p>
<p>
続けるには、<a href="nextpage.php?<?php echo htmlspecialchars(SID); ?>">ここをクリック</A>
してください。
</p>
XSSに関係する攻撃を防止するためにSIDを出力する際に、 htmlspecialchars()を使用します。
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 — セッションデータを書き込んでセッションを終了する
セッション
13-Jan-2008 07:26
12-Jan-2008 11:34
I too ran into the problem of session data being different across the site when "www" was used and not used, so here's a proposed fix if you cannot easily change your "www" access for your web site. (Note: I used $HTTP_HOST rather than $_SERVER["HTTP_HOST"] and $PHP_SELF just for ease of reading)
if($HTTP_HOST == "myhost.net")
header('Location: http://www.myhost.net' . $PHP_SELF);
you can also use:
if($HTTP_HOST == "www.myhost.net")
header('Location: http://myhost.net' . $PHP_SELF);
Just throw that in a PHP file and include it at the top of all your PHP pages that are accessed. This way, before sessions are even used in a script, the access path is right. I think it should work out just fine. Hope it helps anyone with similar issues.
19-Dec-2007 04:10
Hey people,
This caused a minimal amount of discomfort, but however was quickly solved when I peeked in the php.ini and saw that the entire 'session.save_path' was commented out! This must have been from the version change from 5.0 to 5.2, and sessions naturally began to work correctly when I removed the comment token and filled in the value like so (using Apache):
session.save_path = "c:\Windows\Temp"
Maybe this will serve as a starting point and save some time for some of you out there who start from a fresh php.ini.
--Matthew
01-Oct-2007 01:45
Another gotcha to add to this list is that using a relative session.save_path is a VERY BAD idea.
You can just about pull it off, if you're very careful, but note two related points:
1) The path is taken relative to the directory of the ORIGINALLY executed script, so unless all pages are run from the same directory, you'll have to set the directory separately in each individual subfolder
2) If you call certain functions, such as session_regenerate_id(), PHP will try to take the session directory relative to the exectuable, or something like that, creating an error IN the executable. This provides slightly cryptic error messages, like this:
Warning: Unknown: open(relative_path\ilti9oq3j9ks0jvih1fmiq4sv1.session, O_RDWR) failed: No such file or directory (2) in Unknown on line 0
Warning: Unknown: Failed to write session data (files). Please verify that the current setting of session.save_path is correct (relative_path) in Unknown on line 0
... so don't even bother. Just use
<?php ini_set("session.save_path",dirname(__FILE__)."/relative_path"); ?>
(or equivalent) in a file which you know is always in the same place relative to the file.
{PHP version 5.1.6}
30-Aug-2007 01:29
A problem i've come up with is when sending a js file to the browser that has session_start in it ie will crack it and not download and execute the file. FF is fine and i think i know what the problem is. ie does not except cookie's for js files being downloaded and session_start is trying to send a message telling it to increase the id time longer even though its already initiated. I can read the session id from the browser, by $_COOKIE["PHPSESSID"] though i dont know of anyway of setting up the session from that without sending a cookie back.
30-Aug-2007 05:58
Careful not to try to use integer as a key to the $_SESSION array (such as $_SESSION[0] = 1;) or you will get the error "Notice: Unknown: Skipping numeric key 0. in Unknown on line 0"
21-Aug-2007 02:54
Please note: PHP Session Variables do not work like ASP Session Variables.
You can't just call a session variable. All you get is the Session ID. With the Session ID you can track the user.
But there are no Session Variables that you can create that work like ASP's Session("VariableName").
12-Aug-2007 08:20
Bruno's posting of mod_files works for default (16) or 32, but it doesn't work for 64. The following isn't great code since I'm not a great shell coder, but it does work better. It replaces the middle section of Bruno's script
hash_chars="0 1 2 3 4 5 6 7 8 9 a b c d e f"
if test "$3" ; then
if test "$3" -eq "32"; then
hash_chars="$hash_chars g h i j k l m n o p q r s t u v"
fi
if test "$3" -eq "64"; then
hash_chars="$hash_chars g h i j k l m n o p q r s t u v"
hash_chars="$hash_chars w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z - ,"
fi
fi
His posting should be updated (and mine should be removed). :-)
28-Jun-2007 10:07
Lima's note on sessions and browser's tabs needs to be modified for my version of php as the call to uniqid('') will return an alphanumeric string.
Hence the ereg statement should be:
if(!ereg('^SESS[0-9a-z]+$',$_REQUEST['SESSION_NAME'])) {...
02-Jun-2007 04:01
Regarding xhtml validation errors with w3c validator:
The problem is the validator doesn't support cookies, so our session_start() mechanism injects hidden input fields just below all form tags (and in urls).
You need to do two things to pass validation:
1) use fieldsets around *all* input fields (for xhtml 1.0+) to pass validation
2) then, before session_start() change the url_rewriter.tags list of tags to drop form and add fieldset:
ini_set("url_rewriter.tags", "a=href,area=href,frame=src,fieldset=");
session_start();
You can also set url_rewriter.tags anywhere, (see appendix for php.ini)
02-May-2007 12:45
To clear out a possible doubt of other readers which have read this part of "Eric dot Deplagne at nerim dot net" note:
--------
In fact, two other variables (at least) play a role in session duration, and will explain that the session might last more than expected. The gc erasing your data is a probabilistic thing. Each time a session is opened, the probability the gc is started is session.gc_probability/session.gc_divisor. session.gc_probability defaults to 1 and session.gc_divisor defaults to 100, which makes a 1% probability.
This is to have sessions long enough. I'm unsure about having sessions lasting exactly the time we want them to.
--------
The gc erasing of the sessions is NOT a probabilistic thing, they are erased ONLY when they are older than the number of seconds specified in "session.gc_maxlifetime" ini setting.
The probabilistic fact is that old sessions will not be erased if the garbage collector is not run frenquently enough, but anyway it is your choice to have a higher or lower "session.gc_probability" on "session.gc_divisor" ratio.
So, talking from the server side point of view, a session can last more than the specified amount of time but not less. And if the client respects the cookies duration (in case of cookie-based sessions) those invalid sessions will not last more than expected.
You finally might want to add a timestamp inside the session and validate its age through it to radically solve the problem, if necessary. Example:
<?php
session_start();
if (!isset($_SESSION['generated']))
$_SESSION['generated'] = time();
else { // if the session is not allowed to live more, regenerate it
if (time() - $_SESSION['generated'] > ini_get('session.gc_maxlifetime'))
$_SESSION = array('generated' => time());
}
?>
28-Apr-2007 12:37
If you try to use your own session handling functions (eg. for saving session data to DB) make sure session.auto_start directive is 0.
The manual warns about not being able to put objects in your sessions with auto_start=1: I guess that for the same reason your customized handling functions are ignored is sessions start automatically.
Hope this saves somebody a few minutes.
18-Apr-2007 03:56
If your session are not retrieving correctly make sure that session.cookie_secure is to set to 'Off' if you are NOT going through https. Everytime you navigate the site your session data will not be retrieved and your sessionid will change. It may be obvious but I spent two days trying to figuring this out. Hope it helps someone.
17-Apr-2007 10:17
Sessions and browser's tabs
May you have noticed when you open your website in two or more tabs in Firefox, Opera, IE 7.0 or use 'Control+N' in IE 6.0 to open a new window, it is using the same cookie or is passing the same session id, so the another tab is just a copy of the previous tab. What you do in one will affect the another and vice-versa. Even if you open Firefox again, it will use the same cookie of the previous session. But that is not what you need mostly of time, specially when you want to copy information from one place to another in your web application. This occurs because the default session name is "PHPSESSID" and all tabs will use it. There is a workaround and it rely only on changing the session's name.
Put these lines in the top of your main script (the script that call the subscripts) or on top of each script you have:
if(version_compare(phpversion(),'4.3.0')>=0) {
if(!ereg('^SESS[0-9]+$',$_REQUEST['SESSION_NAME'])) {
$_REQUEST['SESSION_NAME']='SESS'.uniqid('');
}
output_add_rewrite_var('SESSION_NAME',$_REQUEST['SESSION_NAME']);
session_name($_REQUEST['SESSION_NAME']);
}
How it works:
First we compare if the PHP version is at least 4.3.0 (the function output_add_rewrite_var() is not available before this release).
After we check if the SESSION_NAME element in $_REQUEST array is a valid string in the format "SESSIONxxxxx", where xxxxx is an unique id, generated by the script. If SESSION_NAME is not valid (ie. not set yet), we set a value to it.
uniqid('') will generate an unique id for a new session name. It don't need to be too strong like uniqid(rand(),TRUE), because all security rely in the session id, not in the session name. We only need here a different id for each session we open. Even getmypid() is enough to be used for this, but I don't know if this may post a treat to the web server. I don't think so.
output_add_rewrite_var() will add automatically a pair of 'SESSION_NAME=SESSxxxxx' to each link and web form in your website. But to work properly, you will need to add it manually to any header('location') and Javascript code you have, like this:
header('location: script.php?'.session_name().'='.session_id()
. '&SESSION_NAME='.session_name());
<input type="image" src="button.gif" onClick="javascript:open_popup('script.php?<?php
echo session_name(); ?>=<?php echo session_id(); ?>&SESSION_NAME=<?php echo session_name(); ?>')" />
The last function, session_name() will define the name of the actual session that the script will use.
So, every link, form, header() and Javascript code will forward the SESSION_NAME value to the next script and it will know which is the session it must use. If none is given, it will generate a new one (and so, create a new session to a new tab).
May you are asking why not use a cookie to pass the SESSION_NAME along with the session id instead. Well, the problem with cookie is that all tabs will share the same cookie to do it, and the sessions will mix anyway. Cookies will work partially if you set them in different paths and each cookie will be available in their own directories. But this will not make sessions in each tab completly separated from each other. Passing the session name through URL via GET and POST is the best way, I think.
04-Apr-2007 05:11
'session.cookie_domain' should be set to empty string for all local domain names, not only for 'localhost' (but should not be empty for local IP addresses):
<?php
ini_set('session.cookie_domain', (strpos($_SERVER['HTTP_HOST'],'.') !== false) ? $_SERVER['HTTP_HOST'] : '');
?>
29-Mar-2007 12:06
Multi-site security risk!
Suppose you use session security to determine login status, and you have several such sites on the webserver which essentially assign a session token to determine your login status. A common occurence for webdeveloping companies that have a standard system or package, and are not using a high security setup. (ie all sites share the same session path directory)
PHP sends the browser a cookie and that cookie should only be valid for the site it was retrieved from, but only the browser determines this, the server does not record the path or domain with the session cookie, so technically you could modify the browsers cookie jar to send the same cookie request for a different domain or path than what was originally meant.
This means that if the same session variables are used to determine a logon status on different sites on this server, then the user can access all these sites with the one session id.
The solution is to write the domain and or path as session variables as well, thus when logged on status is checked, the script checks that the session was created through the current domain or path.
13-Mar-2007 06:06
I wanted to retain a session variable's value after a session_unset() and encountered this anomaly: PHP can assign your variable by reference/pointer if your data source is a session variable, even if "&" isn't supplied.
<?
$_SESSION['x'] = "foo";
$x = $_SESSION['x'];
echo $x; // "foo"
$_SESSION['x'] = "bar";
echo $x; // "bar";
?>
To fix this, you can assign your variable to a new variable:
<?
$_SESSION['x'] = "foo";
$x = $_SESSION['x'];
$y = $x;
echo $y; // "foo"
$_SESSION['x'] = "bar";
echo $y; // "foo";
?>
10-Feb-2007 03:26
localhost problem
-----------------
When using localhost and session.cookies not work, simply remove domain from session.cookie_domain.
We can use "session_set_cookie_params" function or ini_set to do this. Example:
$cookie_path = 'my_path';
$cookie_domain = 'localhost'; //or any valid domain
init_session_cookies($cookie_path, $cookie_domain);
//maybe we create new function for handling this
function init_session_cookies($path, $domain) {
if ($domain=='localhost') $domain='';
if (function_exists('session_set_cookie_params')) {
session_set_cookie_params(0, $path, $domain);
} else {
ini_set('session.cookie_lifetime', '0');
ini_set('session.cookie_path', $path);
ini_set('session.cookie_domain', $domain);
}
}
Best,
Parikesit (zae_lokamaya #at# yahoo #dot# co #dot# uk)
31-Jan-2007 01:57
url_rewriter.tags = "a=href,area=href,frame=src,fieldset="
Modifying url_rewriter.tags to the above line in the php.ini file gave me mixed results, including some pages adding the sessionid after BOTH the form tag and the fieldset tag.
Then I noticed the comment at the top of the php.ini file: "If you modify the file, you must copy it to all subdirectories that contain php." This has to do with the search order php uses to find the php.ini file. PHP looks in the current working directory first.
Works.
30-Jan-2007 07:35
In reference to the IE6 issue that results in loss of session data after a page refresh, I found a solution. In my case, the host that was experiencing the issue contained an underscore (host_dev). Apparently underscores are not valid in host names and IE is the only browser that seems to care. I removed the underscore and all is well. I found this information here: http://us2.php.net/manual/en/function.setcookie.php#67262
02-Jan-2007 09:47
jmoore at sober dot dk wrote: "Note: Changing sessions to use a directory other than /tmp will be harder to find, but no more secure."
This is true. I used to think that this could be solved by storing sessions in a different folder that is accessible only by apache, but the reality is that assuming you are only running a single apache server (as any shared host will), every user can command apache to retrieve that data.
The best solution is to store session data in a database by writing (and informing PHP about) specific session handling functions that store the data using a private username and password that only you know. There is a good discussion of this in Essential PHP Security by Chris Shiflett (O'Reilly Books).
Bruno's shell script below is very helpful for those who want to customize their session storage. I would only warn that there is a typo in his instructions. He states that the script should be called as:
./mod_files.sh ./mod_files.sh /tmp/session 3 32
But you should only type mod_files.sh (or whatever the name of your script file is) once, not twice. It doesn't need its own name as an argument.
Also - make sure you don't make the silly mistake I did of naming your script file "script" and then trying to call it with the argument:
script /tmp/session 3 32
...because "script" is the name of a real Unix function, which will launch a completely different function and then overwrite your original file with whatever you type after that. If you do that by accident, you will need to type "exit" to get out of the script recording mode, and then replace your script file. Also, you have to include the './' prior to the name (i.e. './mod_files.sh' instead of 'mod_files.sh') unless you are running the script from the folder where you installed it, because the location where you are installing this probably (hopefully!) isn't in your PATH shell variable.
22-Dec-2006 05:20
Be careful when using use_trans_sid and javascript together. When adding a form dynamically with javascript, you usually need to put it in quotes and use addslashes() for your html code.
This will nicely put slashes into the code for your form and the javascript will work perfectly. Or so you would think. PHP does recognise the form, even with the slashes added. So it will neatly insert a hidden variable to your form, with the name of your session variable and the value of the session ID. This hidden variable isn't slashed though, and it may break your javascript code.
The only solution I came up with, is to manually add the hidden variable, before applying the addslashes() function. It will then be shown correctly, and PHP will not insert the hidden value. Of course you may get both a cookie and the variable, depending on your settings, but it does work.
14-Dec-2006 01:25
Note on using (the excellent!) Sharedance:
Sharedance as of 0.6 doesn't do any kind of locking. It works well for an application cluster (which I'm using) and allows concurrent writes, which means that the "last one to write wins" order stands. (which has virtually no effect on how I use sessions)
05-Dec-2006 05:59
The session variable is still lost when navigating even if I change $setting or $_SESSION['setting'].
If you assign a session subscript/key to the same name as a variable, the session variable will be volatile and lost upon navigating.
For example, if passing a setting that you want in $_SESSION, don't do this:
<?
$setting = $_REQUEST['setting'];
if (!empty($setting))
$_SESSION['setting'] = $setting;
?>
Instead, rename $setting or $_SESSION['setting'].
To Jestin S Larson :
Your generated ids arent safe, they are guessable because depending only on guessable vars. You must add a random var to your id (ie in md5( ... ) )
27-Nov-2006 03:19
If you want the simplest way there is to log a session out after 30 minutes (or any other period of inactivity) simply add a second line after session_start(), like this:
session_start();
setcookie("PHPSESSID",$_COOKIE['PHPSESSID'],time()+1800);
Where 1800 is the time in seconds before the session should expire. PHPSESSID is the default session ID. This way, every time a user loads a page they get their session extended.
06-Oct-2006 09:39
In response to marou at marou dot com responding to fondman at hotmail dot com regarding local variables overwriting SESSION variables:
I was encountering this same problem. On my local PHP 5 server, no problem. Remote host's server running PHP 4: major headaches.
Initially, I concluded it was some kind of bug in PHP 4 and older. However, according to the devs, this is not a bug (see http://bugs.php.net/bug.php?id=36366). Apparently, this is intended behavior when register_globals is set to ON.
But, as noted elsewhere in the docs, register_globals cannot be turned off at runtime using ini_set(). However, you can use a local .htaccess or php.ini to override the setting. This site helped me solve the problem:
http://www.nyphp.org/phundamentals/ini.php
Full details of my experience with this issue can be found here:
http://tinyurl.com/o6p7y
05-Oct-2006 10:59
Jestin's Session class is a nice alternative, but I had trouble with it. The results of the filesize() function are cached. I ended up having to put a call to clearstatcache() at the head of Session::_getdata(); Otherwise, your session data gets truncated.
13-Sep-2006 09:02
old problem was:
internet explorer has security settings which reject your php session cookie within different framesets (third party cookies). one approach to handle this was to pass the session id to the other frames in the url. the www says, this is a little bit unsafe...
another trick to handle this is, to trick the explorer with the php header funktion. as described in the microsoft knowledgebase
article http://support.microsoft.com/kb/323752/EN-US/
you simply add a header at the top of your scripts _bevore_ the session_start() is called:
header('P3P: CP="CAO PSA OUR"');
and now test it and enjoy...
09-Sep-2006 09:03
I spent about 8 hours debugging a problem with sessions and redirecting, and I finally found the problem, which after looking back, should have been the first thing I tried.
I use sessions to prevent hotlinking, so if someone hotlinks my file, I will redirect them to a different page by re-writing the header information. When I redirected, I sent path information in the GET data about the file they were trying to access. Long story short, when I redirected with a forward-slash "/" AFTER the .php, the page would create a different session ID than the rest of my domain was using. This happened despite the fact that the cookie path was set to "/" (which should have captured any path on my domain).
The issue was even harder to figure out, because the page with the wrong session ID was NOT creating a second cookie. The only cookie was the one with the proper ID, but the broken page did not use this cookie (where then, did it get this ID from?).
To fix the problem, I simply removed the forward-slash from the GET data (base64_encoding works nicely).
I imagine this is an issue with my browser parsing the url, but I tried both Opera and Firefox (IE doesn't load anymore :/) and both browsers showed the same problem.
I looked into hidden header data, failure to write the cookie, trans_ses_id (even though it was set to false), HTTP_HOST, everything, but in the end it was just a stupid forward-slash that had done me in.
02-Sep-2006 03:56
Similar to the use of captcha images you can easely track and advise user who don't accept cookies, especially no session cookies without redirecting them.
so here's the deal:
if the main script (which outputs the html) doesn't have a value in it's session which says that a session is running successfully a different value is saved in the session and an image is included in the html which checks wether the session-check value is set or not.
If it's set the image-script sets a confirming value which will verify the session to be running correctly and output a transparent 1*1px gif.
If the value is not set the image outputs an advising image which tells to allow cookies.
You can also wrap the image with a link who refers the user to a page addressing the cookie issue. If the 1px trans is generated the user will hardly find the link, but if the error-image is generated he will surely be able to click it.
pros:
- works
- no rerouting, you can see the result on the first page opened by the user
- no javascript
cons:
- bad accessebility (if you give the image an alt-text any blind user will read it at least on the first call, but you cold also write this into the alt text... so maybe there are no cons)
i hope this'll help
24-Aug-2006 10:19
Some users turn off cookies on their browser. It would be nice to advise such users that they need to switch on cookies to use your web site, especially if you do not allow URL session IDs.
The first request to your site will not contain cookie data from the user. Some developers do a little trick on the server at this point to redirect the user to the same or different page and in so doing endeavour to deliver a cookie so that it can then be determined if this was successful on the second request. It has the advantage of letting the no-cookie user know at the on-set if there is a problem. Of course this adds an overhead of time and server resources. It also might impare your site's position with popular search engines.
So, since many sites will work to a point without sessions working (i.e. scatterings of static links and basic searches), I allow the user to load the first page and then perform the cookie check upon the user's subsequent request. If the cookie canot be found I place advice text accordingly
simple (unchecked) solution...
function cookie_check() {
if (!isset($_COOKIE['PHPSESSID'])) {
return false;
} else {
return true;
}
if (!cookie_check()) {
echo "This site uses cookies, dah dah dah...";
}
I have looked fairly extensively for information on this issue but there isn't a great deal about. So, if anyone out there has more experience of this...
24-Aug-2006 01:09
I just went looking through the /tmp dir on a shared hosting server, and noticed all the php sessions stored there (bad idea for shared hosting). I noticed that some of these people/scripts are storing plain-text passwords in their sessions (another very bad idea). Here's a hint people: do not store ANYTHING that may present a security risk in the session data! This includes, passwords, creditcard information, etc.
It is best, under ALL circumstances that a dir other than /tmp be used for session data. Btw, whomever it was that said it was no more secure to use a diff dir was wrong. The /tmp dir is a globally readable/writable dir.
If you are using shared hosting, then you better be sure your session data is being saved within your home dir and NOT web-accessible. If you are a shared hosting sysadmin, you should be doing this for your users automatically... as well as any other tmp files (file uploads, etc...).
10-Aug-2006 07:08
It should be noted that PHP makes the decision about whether SID is empty based on the HTTP request. Specifically, if there is no cookie sent with the GET or POST request, SID is populated when the session is initiated.
What does this mean? If you want your site to support clients who have cookies disabled, your links will have PHPSESSID appended to them on the page where the session is created.
It seems like the only way around this is a double redirect...
01-Aug-2006 07:34
One more note on session duration, and especially long sessions. I hope I've now understood the problem, and this may be useful.
The duration of a session is indeed controlled by many things (too many for my taste).
The first thing is session.cache_expire, which should be *the* thing, you can set it with ini_set(), or with session_cache_expire(). The value is in minutes, and defaults to 180, which is 3 hours and should be enough.
<?php //ini_set("session.cache_expire","180"); // default is 180, which is 3 hours... ?>
But that does not work !
Second thing to take into account, session.gc_maxlifetime. Indeed, if the garbage collector kills your session data, you're lost. So we set it with ini_set. The value is in seconds, and defaults to 1440, which is only 24 minutes and might be a little short.
<?php ini_set("session.gc_maxlifetime","3600"); // default is 1440, which is only 24 minutes ?>
Here I should have a 1 hour session. But in fact, I don't !
Third thing to take into account, session.save_path. If other people mess up with it, like if it's "/tmp" as it is by default, and their gc has not the same idea as yours, you're lost. So we set it with ini_set or session_save_path.
<?php session_save_path("/my/own/path/without/url/sessions"); ?>
Here we are. As you can read in the example it should be a path you control (and your web server can write), with no access via URL.
Of course, all these parameters must be set before calling session_start().
In fact, two other variables (at least) play a role in session duration, and will explain that the session might last more than expected. The gc erasing your data is a probabilistic thing. Each time a session is opened, the probability the gc is started is session.gc_probability/session.gc_divisor. session.gc_probability defaults to 1 and session.gc_divisor defaults to 100, which makes a 1% probability.
This is to have sessions long enough. I'm unsure about having sessions lasting exactly the time we want them to.
26-May-2006 03:34
If you have a value specified for session.referer_check you may run into difficulty when someone accesses your site and attempts to log in with a mis-capitalized URL. The logon will fail because any calls to session_start() will result in the existing session being trashed and a new one being created. This becomes a bigger problem when the logon is followed by a header("Location: ...") redirect, because the session_start() at the top of the page will fail.
Because session_start() always returns true, it's not obvious how to detect when the referer check fails. To detect it, I have come up with a method which compares the intended session id with the session id after session_start() is run. If they are different, the user is redirected to the proper location. This example uses a technique to avoid session id fixation, as well.
ini_set('session.referer_check', 'www.yourdomain.edu/ltr/');
ini_set('session.use_only_cookies', 1);
session_name('yourapp'.str_replace('.', '', $_SERVER['REMOTE_ADDR']));
session_start();
if($_GET['badreferer'])
echo 'You tried accessing the site with a bad URL. Try logging on again.';
if(isUserAuthed($name, $pass))
{
$old_sessid = session_id(); //save current session id so we can delete it later
if( !session_regenerate_id() ) //get a new session id (must do this before destroying the old session)
die("Couldn't regenerate your session id.");
$new_sessid = session_id(); //save new session id so we can get back to it
session_id($old_sessid);
unset($old_sessid);
session_destroy(); //destroy the session they got before they logged in
session_id($new_sessid);
session_start(); //start the new session
$_SESSION = array(); //not really necessary any more, but still a good idea
if(session_id() != $new_sessid)
{
/*If this is true, then the session_start() failed to work properly. If session_start() failed to work properly, the most likely cause is that the referer url is different from that set in fuxebox.ini on session.referer_check. The most common cause of this is URL capitalization problems. Therefore, we relocate them to the proper URL, and set a flag to display an error because we can't use pushError() if the session isn't valid. */
$good_url = ini_get('session.referer_check');
header('Location: http://'.$good_url.'?badreferer=1');
exit;
} else {
unset($new_sessid);
//Set session variables here
$_SESSION['isloggedin'] = 1;
echo 'You have been logged in.';
}
}
19-May-2006 08:07
POST the variable can give the page Expire Warnig when you press the BACK button.
Solution: Put this code on the page top.
<? session.cashe.limiter(‘private, must-revalidate’) ?>
09-May-2006 11:14
I just finished a marathon debugging session with sessions, and I wanted to share what I learned with the rest of the PHP community because this has been a problem I've battled on several projects before finally solving it today.
I am using sessions to register a user's ID, and every so often, for no apparent reason, the session would seem to expire and my logged-in user would get kicked out.
This is the code I am using to validate a user:
<?php
session_start();
$auth = false;
if (isset($_SESSION['user_id'])) {
$user = new User($_SESSION['user_id']);
$auth = true;
else {
$login = $_REQUEST['login'];
$password = $_REQUEST['password'];
$login = clean($login);
$password = clean($password);
// clean() is my own function to escape quotes and so on
$user = checkLogin($login,$password);
if (!is_null($user)) {
$auth = true;
}
}
if (!$auth) {
die("you must log in.");
}
// etc etc ... //
?>
I was scratching my head as to why, on about 10% of the times I sent a user to a new page (a PHP page that didn't have any of the sessions stuff--no session_start() and no mention of any session variables), when they came back the session variables were all empty.
I came upon a clue when I used ini_set to change the session.save_path location. My idea was that maybe the session files in /tmp were being deleted by other users on the system or something. So I added this line before session_start():
<?php
ini_set('session.save_path',"/path/to/unique/dir/");
?>
I knew no one else was saving their sessions there, so I started logging in to my page and at the same time checking for the creation of new sess_* files. I noticed that sometimes, especially when I had problems, a second session file (that was empty) would appear.
What I realized was that the URL was changing from www.coryforsyth.com to coryforsyth.com. When the presence of the WWW changed, PHP thought it was a different session and created an empty one that caused my script to log me out. If I went to the location bar of my browser and added/removed the WWW (to the way it had been before), all was well and I was still logged in.
An incredibly thorny problem. I hope this post helps someone else fix it, or even better prevent it. I changed my hosting preferences to automatically add a WWW to my domain if it wasn't typed that way.
thanks,
Cory Forsyth
18-Apr-2006 04:15
Session locking (concurrency) notes:
As mentioned several times throughout this section on Sessions, the default PHP session model locks a session until the page has finished loading. So if you have two or three frames that load, and each one uses sessions, they will load one at a time. This is so that only one PHP execution context has write access to the session at any one time.
Some people work around this by calling session_write_close() as soon as they've finished writing any data to the $_SESSION - they can continue to read data even after they've called it. The disadvantage to session_write_close() is that your code still will lock on that first call to session_start() on any session'ed page, and that you have to sprinkle session_write_close() everywhere you use sessions, as soon as you can. This is still a very good method, but if your Session access follows some particular patterns, you may have another way which requires less modification of your code.
The idea is that if your session code <b>mostly</b> reads from sessions, and rarely writes to them, then you can allow concurrent access. To prevent completely corrupted session data, we will lock the session's backing store (tmp files usually) while we write to them. This means the session is only locked for the brief instant that we are writing to the backing store. However, this means that if you have two pages loading simultaneously, and both modify the session, the <i>Last One Wins</i>. Whichever one loads first will get its data overwritten by the one that loads second. If this is okay with you, you may continue - otherwise, use the session_write_close method, above.
If you have complicated bits of code that depend on some state in the session, and some state in a database or text file, or something else - again, you may not want to use this method. When you have two simultaneous pages running, you might find that one page runs halfway through, modifying your text file, then the second one runs all the way through, further modifying your text file, then the first one finishes - and your data might be mangled, or completely lost.
So if you're prepared to debug potentially very, very nasty race conditions, and your access patterns for your sessions is read-mostly and write-rarely (and not write-dearly), then you can try the following system.
Copy the example from session_set_save_handler() into your include file, above where you start your sessions. Modify the session write() method:
<?
function write($id, $sess_data)
{
global $sess_save_path, $sess_session_name;
$sess_file = "$sess_save_path/sess_$id";
if ($fp = @fopen($sess_file, "w")) {
flock($fp,LOCK_EX);
$results=fwrite($fp, $sess_data);
flock($fp,LOCK_UN);
return($results);
} else {
return(false);
}
}
?>
You will probably also want to add a GC (Garbage Collection) method for the sessions, as well.
And of course, take this advice with a grain of salt - We currently have it running on our testing server, and it seems to work OK there, but people have reported terrible problems with the Shared Memory session handler, and this method may be as unsafe as that.
You can also consider implementing your own locks for scary concurrency-sensitive bits of your code.
08-Apr-2006 11:52
********************WARNING***********************
There's a bug in Internet explorer in which sessions do not work if the name of the server is not a valid name. For example...if your server is called web_server (_ isn't a valid character), if you call a page which uses sessions like http://web_server/example.php your sessions won't work but sessions will work if you call the script like this
[IP NUMBER]/example.php
Took me a lot of time to find out why my PHP sessions worked perfectly in Firefox and Opera but they didn't work in internet explorer
***************************************************
01-Apr-2006 09:47
Fairly new to PHP, I've been looking to alter session timeouts on a shared host where I don't have direct access to configure php.ini. There doesn't appear to be any easy way to find out how to do this in this manual (nor from a quick web search).
The code below seems to work OK to set session timeout. a timeout of 30 secs is used for convenient testing. gc settings must come before session_start().
The garbage collection is made 100% by setting probability and divisor to the same value - if I have correctly understood what these functions do.
(on the first pass of the file, there is no session file - that's established only when the script ends for the first time. Keep reloading to test).
Comments welcome.
<?php
ini_set('session.gc_maxlifetime',30);
ini_set('session.gc_probability',1);
ini_set('session.gc_divisor',1);
session_start();
// check to see what's happening
$filepath = ini_get('session.save_path').'/sess_'.session_id();
if(file_exists($filepath))
{
$filetime = filemtime ($filepath);
$timediff = mktime() - $filetime;
echo 'session established '.$timediff.' seconds ago<br><br>';
}
?>
09-Mar-2006 03:35
I had users of my site occsaionally complaining that they were being logged out after short times of inactivity (usually when they were creating content to send to the site). I had a high cookie timout so I couldn't understand why this was happening, and I never managed to replicate the behaviour myself.
I've just come accross the "gc_maxlifetime" property. This seems to be the culprit; it's set to only 24 minutes! The worst part is that it combines with the "gc_probability" property to produce unpredictable results. I'm mysified as to why the time limit is so low by default, but hopefully increasing it will fix up my errors.
02-Mar-2006 03:19
I just spent a lot of time trying to figure out why my session variables were not available after I seemed to have set them(could echo after setting). I use the same script for several different functions, so the user may reload the page for other purposes. Someone else posted the use of session_write_close(); before a Location redirect. This also worked in put this after I set the session variables the variables are available when the page reloads for another function.
$_SESSION['guid'] = $guid;
$_SESSION['userdata'] = $response;
session_write_close();
01-Mar-2006 08:17
Please Note;
Internet explorer users beware.
When using session_start() to begin a session this session will remain open until the page has finished loading or it is explicitly terminated.
You can lose the session however if the the page contains a reference to <img src=""> with name and id references (which may be used if the image is referencing a dynamic image, called by javascript) This seems to casue IE6 to refresh the page session id and hence loose the session.
This took hours for me to diagnose when users were getting unexpectedly logged out of my site due to this "" in the img src.
01-Mar-2006 02:10
Important note that it just took me the better part of two hours to figure out: Even if you're using session_write_close(), calling exit after a redirect will eat your session variables. I had the following:
Source of register.php:
<?PHP
// Some files included here
// Process our posted form data
$result = processPost();
if ($result)
{
redirect('success.php');
}
else
{
redirect('failure.php');
}
exit;
?>
processPost() was setting a couple of session variables, including an error message, but neither results page was seeing those variables. I removed the exit call from the register page, and all works fine.
/bonks self
22-Feb-2006 05:57
If you're having trouble with unset($_SESSION[$something]) working, here's what I discovered (Win2K/PHP 5.x.x). Assume you want to step through $_SESSION and delete (i.e. unset) certain elements. So,
foreach ($_SESSION as $key=>$value) {
if (stristr($key,'something_to_delete')) {
echo "Will unset $key that has value of $value";
unset($_SESSION[$key]);
}
What I found was that although the $_SESSION elements were deleted in memory, the actual session file was not being written out with the changes (even after using session_write_close). What fixed it for me was to COPY $_SESSION INTO A DUMMY ARRAY, THEN STEP THROUGH THAT DUMMY ARRAY TO FIGURE OUT WHICH ELEMENTS OF THE REAL $_SESSION TO DELETE. I.e.
foreach($_SESSION as $key=>$value) {
$dummy[$key]=$value; // copy to a dummy array
}
foreach ($dummy as $key=>$value) {
if (stristr($key,'something_to_delete')) {
echo "Will unset $key that has value of $value";
unset($_SESSION[$key]);
}
It appears that as you're stepping through the actual $_SESSION array in a foreach, if you unset elements of it, those changes won't be recorded to the session disk file.
'Course then again, my coffee is running low so I could be wrong. But hopefully it's something others can try who might be having a similar problem.
In response to "djohnson at jsatech dot com", posted 09-Dec-2005 09:00
"Be warned, when working with tab-based browsers like Opera and Firefox, sessions are preserved across tabs....IE deals with sessions just fine. There is probably some way to adjust the settings in Firefox or Opera, but that is not the default, and will affect most users."
In fact, the way sessions are managed among different browsers is not all that different among MSIE and Opera and Firefox. You will find that MSIE sessions can be maintained across browser windows, just like in FF or Opera. However the difference that djohnson noted is because of the way MSIE windows are created vs FF and Opera.
If you choose, in MSIE, "File->New Window", you will find that PHP sessions are preserved from browser window to browser window.
If, OTOH, you start a new window of MSIE using the start menu or desktop icon, a new instance of MSIE, with a new process ID, is started. *This* instance does not have anything to do with any other previously existing MSIE instances, and, thus, PHP sessions started in this new MSIE process are distinct from PHP sessions in existing MSIE instances.
See the difference?
Whereas FF and Opera apparently always start a new window into an existing FF or Opera process. Thus PHP sessions are always maintained across browser instances with FF and Opera.
15-Feb-2006 12:15
FreeBSD users, instead of modifying the PHP5 port Makefile, you can either install the session extension using the www/php5-session port, or you can install several extensions at once (you can pick them from a menu) using the lang/php5-extensions port. Same goes for PHP4
02-Feb-2006 02:31
If you're running FreeBSD, and installed php5 (have not checked 4) from the ports, and are getting errors saying the session functions are undefined, try running phpinfo(). You'll probably see that the '--disable-all' configure command was used. To fix, edit the /usr/ports/lang/php5/Makefile, and remove the '--disable-all' line. In that directory, run a 'make deinstall', if you installed already. Next, run 'make install' while still in that same directory. It should work fine after that.
26-Jan-2006 05:23
If you are wondering why your garbage cleanup method is not being called, read on.
The manual notes for garbage cleanup state that the session.gc_divisor defaults to 100:
[code]
//http://php.net/manual/en/ref.session.php
session.gc_probability ... Defaults to 1.
session.gc_divisor .... session.gc_divisor defaults to 100.
[/code]
This would provide a gc probability of 1 in 100 ie. your garbage cleanup is going to be called 1% of the time.
Conversely, my PHP 5.1.1 install, compiled from source, contains this in the php.ini-recommended file (and my php.ini file):
[code]
; Define the probability that the 'garbage collection' process is started
; on every session initialization.
; The probability is calculated by using gc_probability/gc_divisor,
; e.g. 1/100 means there is a 1% chance that the GC process starts
; on each request.
session.gc_probability = 1
session.gc_divisor = 1000
[/code]
A 0.1% probability by default. Based on the information provided, I set my gc_probability to 100, thus providing a 1% probability stale sessions would be culled.
Moral:your local php.ini may differ from what the manual provides.
24-Jan-2006 11:56
If you're using sharedance to distributed php sessions across a group of machines beware of the following:
On a freebsd 6.x system I have observed a huge performance hit caused by dns/host file lookups.
To ensure maximum performance using sharedance you should set the 'SESSION_HANDLER_HOST' constant to an IP rather than a hostname.
When i did this my requests per second jumped from 55 to 389 requests per second!
21-Jan-2006 08:00
If you set the session_id through the calling URL, it *will not* set the session cookie in 4.4.2.
For example:
www.example.com/?PHPSESSID=foo
This will set the session id to 'foo' but it won't actually set the session cookie. The last known version I'm aware of is 4.3.3 where it will set the cookie.
This doesn't appear to be definitively mentioned in here anywhere. But according to the devs, it's not a bug. Hopefully this knowledge will help you out if you're experiencing the same problem.
17-Jan-2006 06:19
This is just to note that I was able to fix my problems due to the many helpful comments here.
The problem I was having was as follows:
a) I was dynamically generating a file to download
b) When the user clicked "Save" in MSIE, and then imported the download file into the application, all was well.
c) When the user clicked "Open" to directly import the file, the application would throw an error.
I believe what was happening is that the browser was not saving a local copy of the file due to the "no-store" directive, when the user clicks "Open" directly.
Therefore the examples above regarding pragma & cache-control were useful to resolving it.
Thanks for all the help. I just want to add also that the following web page was of great help to see the actual HTTP headers being sent by the web app: http://www.rexswain.com/httpview.html
Much easier than doing telnet to port 80! Hope this helps other also.
Andrew Royappa
27-Dec-2005 12:12
In answer to..
-PHP SESSIONS NOT WORKING in with windows---
...solution on the session cookie path.
I am running Apache 2 and PHP 4.4.0 on a Windows XP SP2.
...
----------------------------------
It was a small mistake in my directory stucture,
I have changed from c:\temp to c:\Temp as I had directory called "temp" not "Temp".Now session is working properly in my case.
Make sure directory name is same, in windows environment too.
23-Dec-2005 01:49
In reponse to fondman at hotmail dot com with the 4.4.0 issue with local variables replacing session variables.
It also happens in 4.4.3.
I have a development environment set up with 5.0, and the production environment is 4.4.3. I had set some local variables with the same name as one of my session variables. It did the same thing you described on the production box, yet worked fine in development.
Just an FYI.
20-Dec-2005 11:55
The vanilla implementation of session will blindly spew back the value of the session_id that the user sends it after URL decoding it. This can be used as an attack vector, by including strings like "%0D%0ALocation:%20http://someothersite.com/%0D%0A" in the cookie. Never trust user input, always cleanse it. If you only expect alphanumerics in the session hash, reject any session_id that doesn't contain it.
<?php
if(!preg_match('#^[[:alnum:]]+$#', $_COOKIE['session_id'])) {
unset($_COOKIE['session_id']);
}
session_start();
?>
05-Dec-2005 06:18
to johnlonely at gmail dot com
the sesion.cookie_path should be used for cookie security. The cookie_path is the path on the server for which the cookies are valid.
i.e. www.example.dom/mywepage/
if cookie_path="/mywebpage"
then
www.example.dom/someonespage/
will not have access to them. I use this parameter without problems.
I'm not saying that this will make cookies secure, but certainly others of www.example.dom will not have access to them.
However, if you have other directories say www.example.dom/niftystuff that you want the cookie to be valid for, then cookie_path needs to be "/".
This is better for servers that use the /~user/ user aliasing.
26-Nov-2005 08:39
As the reference mentions the value of the register_globals variable can cause some problem if you use sessions for verification.
If GET variables are registered as global and you check whether the user is already logged in like this:
<?php
if ($_REQUEST['password'] == "right_password") {
$password = true;
session_register('password');
}
//...later on:
if ($password) {
//secure content
}
?>
Notice, that if you guess the name of the verification variable and pass it through the URL (index.php?password=true) and the register_globals is true then a script like this lets you in.
I know this is a stupid mistake, but maybe I am not the only one who made it...
So after you registered the $password var, you should check the login with session_is_registered() function:
<?php
if (session_is_registered('password')) {
//secure content
}
?>
This function cannot be fooled by GET or POST variables...
Hope it's a useful note!
24-Nov-2005 06:35
It took me long to understand how the SID was passed when cookies are disabled, and session.use_trans_sid set to 1.
The doc says it passes through the URL, which is true, when there's no form in the page. In that case, you can see the SID in the URL.
If the page contains a form, PHP automaticaly adds a hidden field it uses to pass the SID by POST. In that case, the SID is invisible in the URL.
Hope it helps.
20-Nov-2005 01:39
[editors note]
It should be noted that it's highly recommended to store sessions for each virtual host in seperate directories or in a database.
[/editors note]
I just noticed that it's possible to access the same session through multiple apache virtual hosts.
So keep this in mind when using sessions for anything sensitive, and make sure to encrypt the data (using the mcrypt functions for example, when available).
10-Nov-2005 11:10
> Note: The arg_separator.output php.ini directive allows to customize the argument seperator. For full XHTML conformance, specify & there.
Exactly the same rule applies to HTML as well, there is abolutely no reason why this should not be set to & by default. The only difference is that in XHTML, XML error handling defines that it's a well formedness error. For HTML, error handling was not so well defined nor sanely implemented and tag soup parsers just accept it, but that doesn't make it right.
arg_separator.output *MUST* be set to either of these if you're outputting either HTML or XML:
arg_separator.output = "&"
arg_separator.output = ";"
http://www.w3.org/QA/2005/04/php-session
07-Nov-2005 04:27
If you want to receive the functionality of session.use_only_cookies but are using a PHP version prior to 4.3.0, here's an easy way:
if (isset($_GET['PHPSESSID'])) {
exit;
}
This assumes:
session.name = PHPSESSID
Is set in /etc/php.ini
24-Oct-2005 03:26
If you have trouble with Internet Explorer 6 and non-working sessions (all session-data is lost after clicking on a link), please look user-hints for setcookie().
You have to add the following line after session_start() to get sessions working:
<?php
// Initalize session
session_start();
// Send modified header
header('P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"');
?>
23-Oct-2005 11:54
If you would like to ensure your sessions with referer checking you must use iniset() regularly, as
"session.referer_check contains the substring you want to check each HTTP Referer for"
so there is no way PHP can automatically know which URL you are expecting, e.g. it does not assume SCRIPT_NAME or anything else.
I had a serious problem when I tried to disable referer checking with session.referer_check = 0 which of course does not work
12-Oct-2005 03:32
Everytime I upgrade PHP to a new version, I used to recompile the php.ini file. Everytime I create a website, I always kept the php.ini file so that in the future I would be able to retrieve some Unique properties of the php version I used. So the last php version I've seen where session is sticking is version 4.2. I've been trying for two days with no luck searching the manual and forum, when I tried something :
If you guys always fill the
session.cookie_path = /
to somewhere you the cookies should go, then leave the fuss. You'll save two days! Leave it be!
[Session]
session.cookie_path = /
Happy sticking sessions.
06-Oct-2005 11:54
The documentation says that sessions "may" be readable by other users on the system, but since it is so trivial to do, "are readable" is a more accurate statement.
For example, this will display the contents of all sessions:
<?php
exec("cat /tmp/sess_*", $aOutput);
print_r($aOutput);
?>
Note: Changing sessions to use a directory other than /tmp will be harder to find, but no more secure.
19-Sep-2005 07:50
If your are using UTF-8, make sure your source
code editor to do not put the BOM mark
(unicode sign) at the top of your source code. so
it is sent before session_start() causing "headers
already sent" message on httpd error log.
14-Sep-2005 09:26
---PHP SESSIONS NOT WORKING---
addition to fasteddie's solution on the session cookie path.
I am running Apache 2 and PHP 4.4.0 on a Windows XP SP2.
Had the same problem that the cookies are saved, in my case att c:\\tmp, but not recognized at reload of the page. The session.save_path must also be set to blank.
The cookies are stored in c:\\windows\\temp.
So if You do not have activated the garbage collector You can find them there for cleanup and error solving.
08-Sep-2005 06:13
If you want prevent people directly setting, for example, a logged_in session variable to bypass your checks using the url?logged_in=true system, a quick trick is to try the line
if (isset($_GET['logged_in'])) { die("Are you trying to take the mickey?"); }
before you do anything else.
I've not tested this heavily, but I'd value any discussion of its merits and potential flaws ...
01-Sep-2005 10:57
Make sure HTTP_HOST matches the url you are using on the browser. (Fix the Apache ServerName setting).
Otherwise, after saving a completed session, the next page will start a new empty session!
17-Aug-2005 12:43
I hope this helps someone:
---PHP SESSIONS NOT WORKING---
My sessions wouldnt ever load from disk. The sessions would start just fine, and a session file would be created and written to disk. (BTW, I'm on a win XP box, Apache 2.0.54, PHP version 5.0.4.) However, next time I loaded the page, the old session would not be used. Instead, a NEW session was created. For me, this happened no matter what computer I was using, whether it was the server (localhost) or a client (remote). A new session was created EVERY TIME I loaded the page.. it was annoying. After a few hours of googling, I gave up and decided to mess around in the php.ini file. I changed this line:
session.cookie_path = /
to this:
session.cookie_path =
Now, php sessions are loaded properly.
I havent tried many things but I think maybe it is because windows needs backslashes (\) instead of forward slashes (/), and if you just leave it blank, it turns out ok.
09-Aug-2005 02:29
I rewrote adodb's session management class to work across servers with database managed sessions. Take a look at http://phplens.com/lens/lensforum/msgs.php?id=13428
28-Jul-2005 08:33
Another note about session.bug_compat_42 and bug_compat_warn.
[full error message:
"Your script possibly relies on a session side-effect which existed
until PHP 4.2.3. Please be advised that the session extension does
not consider global variables as a source of data, unless
register_globals is enabled. You can disable this functionality and
this warning by setting session.bug_compat_42 or
session.bug_compat_warn to off, respectively."
]
The following short script causes the bug_compat_42 warning to appear.
<?php
session_start();
$_SESSION['var'] = NULL;
$var = "foo";
?>
It took me an hour to find out this :-( - so I post it here to avoid
that more people need such a long time.
Conclusion and test results:
You'll get this warning if $_SESSION['var'] contains NULL and you assign
anything (except NULL) to the global variable $var.
The warning will _not_ appear:
- if $_SESSION['var'] contains anything else - or -
- if you don't use a global variable named $var
25-Jul-2005 04:09
A quick answer to jentulman at NOSPAM dot jentulman dot co dot uk about the redirecting problem with sessions:
Use session_write_close before redirection thus ensure session data is correctly saved before redirection.
It worked for me in all situations of redirection.
19-Jul-2005 05:19
Hello,
I posted earlyer about a issue/bug with Windows servers handling sessions. If you did not read it, it was based on the fact that if you can use ini_set to re-define the session.save_path to a relitive location. PHP will instead use it as the exact location with out looking at the directory where your script is bein execute, thus to say, the session file is not created, or re-read. This of course only occurs if you use <?php reregister_id() ?>. This function is told to open the requested session file, obtain the varibles, regenerate an id for that session, create the new session file and then send the cookie header to the client, of course I did not create this function, so it may not be in that order.
The following code will generate the error that I speak of, and will not successfully generate the new session id, of course like I said above, this only accours on PHP 5 & 5.0.4 under the Windows Environment.
<?php
define("_PATH_TMP", "./tmp");
ini_set('session.save_path', _PATH_TMP);
session_start();
$_SESSION['sid']['obsolete'] = session_id();
session_regenerate_id();
$_SESSION['sid']['replaced'] = session_id();
print_r($_SESSION);
?>
(I know that PHP may use defined constants that include '_' characters at the beggining, if it has not already, but I am taking that chance atm...)
This can simply be resolved by using the following code:
<?php
define("_PATH_TMP", dirname($_SERVER['SCRIPT_FILENAME']) . "/tmp");
ini_set('session.save_path', _PATH_TMP);
session_start();
$_SESSION['sid']['obsolete'] = session_id();
session_regenerate_id();
$_SESSION['sid']['replaced'] = session_id();
print_r($_SESSION);
?>
As you can see it uses the uses the servers environment to assurtain the exact location to the script, then locates the next root directory of it, and then allows you to define the tmp directory.
* Of course, you dont need to use a tmp directory, and this issue only occurse when using subdirectorys, I found that the following works just aswell, but this did not fit my needs!
<?php
define("_PATH_TMP", "./");
ini_set('session.save_path', _PATH_TMP);
session_start();
$_SESSION['sid']['obsolete'] = session_id();
session_regenerate_id();
$_SESSION['sid']['replaced'] = session_id();
print_r($_SESSION);
?>
12-Jul-2005 05:40
Here's one for the 'session disapearing after a rediredt problem'. It's nice and simple but drove me mad for a couple of hours.
I was getting reports of users logging in apparently successfully but not actually being logged in and couldn't replicate it myself.
I had a configuration file called at the begining of my script setting defines for physical and url paths, and users with the problem were coming in on a domain alias so of course the login went fine, but then they were redirected to a different domain and the cookie was pointless.
Not very technical I know but maybe it'll stop someone having to headbang like I did.
23-Jun-2005 12:09
Problems with IE and Content Advisor.
It maybe obvious to some, but as its taken me over a week to sort this out, I will post it here.
If you have Content Advisor enabled in IE, it appears to quietly add an extra GET HTTP request to the root of your website.
This will get processed by your default document, so if your default document is index.php, every legitimate request will be immediately followed by another hit to index.php with a blank query string.
If you increment something in a session, it will be the second hit that has the highest value, but the browser is showing the results of the first GET.
Its easy to see, just add a mail('youremail@address.com') at the start of your default document, turn on content advisor and see how many emails you get !
I have generated a 'pics-label' and added to the META tags on every page and this appears to make IE happy.
You can get a pics-label at www.icra.org.
Hope this helps
19-Jun-2005 03:37
The note regarding url_rewriter.tags and XHTML conformity in the manual is bit confusing; it's applicable only when we use <fieldset> tags. Refer http://bugs.php.net/13472
HTH,
R. Rajesh Jeba Anbiah
16-Jun-2005 08:52
Session data is not available to an object's __destruct method as sessions are closed before the object is 'destroyed'.
14-Jun-2005 11:44
Having to use transparent on a system where trans_sid was not compiled, I came up with the folowing ob_start handler:
<?php
function ob_sid_rewrite($buffer){
$replacements = array(
'/<\s*(a|link|script)\s[^>]*(href|src)\s*=\s*"([^"]*)"/',
'/<\s*(a|link|script)\s[^>]*(href|src)\s*=\s*\'([^\'<>]*)\'/',
);
$buffer = preg_replace_callback($replacements, "pa_sid_rewriter", $buffer);
$buffer = preg_replace('/<form\s[^>]*>/',
'\0<input type="hidden" name="' . session_name() . '" value="' . session_id() . '"/>', $buffer);
return $buffer;
}
function pa_sid_rewriter($matches){
$buf = $matches[0];
$url = $matches[3];
$url_orig=$url;
if ($url[0]=='/' || $url[0]=='#' || preg_match('/^[A-Za-z0-9]*:/', $url))
return $buf;
$ses_name = session_name();
if (strstr($url, "$session_name="))
return $buf;
$p = strpos($url, "#");
$ref = false;
if($p){
$ref = substr($url, $p);
$url = substr($url, 0, $p);
}
if (strlen($url)==0)
return $buf;
if (!strstr($url, "?"))
$url.="?";
else
$url.="&";
$url.=session_name() ."=".session_id();
if($ref)
$url.=$ret;
return str_replace($url_orig, $url, $buf);
}
?>
It adds a field to urls and a fake form entry.
You can start the rewrite by doing the folowing at the start of the script:
<?php
function pa_set_trans_sid(){
if ( defined('SID') ){ // use trans sid as its available
ini_set("session.use_cookies", "0");
ini_set("session.use_trans_sid", "true");
ini_set("url_rewriter.tags", "a=href,area=href,script=src,link=href,"
. "frame=src,input=src,form=fakeentry");
}else{
ob_start('ob_sid_rewrite');
}
}
?>
29-Mar-2005 02:10
hi all,
i've been troubles with sessions at my production server for weeks and today i've noticed the problem.
If you use /tmp as php sessions file dir, on a procuction server, system garbage will delete randomly files when a certain number os files are stored at tmp, so some sessions are deleted within 1 seconds, like my case.
Solution? use another dir for php sessions file, and be careful of using a shell script for your own garbage collection, called from cron, with this line:
cd /path/to/sessions; find -cmin +24 | xargs rm
Spud.
02-Mar-2005 11:15
It's true that session variables are stored on-server, but for the server to know which session the user is using, a cookie is used. If you check your cookie cache, you'd see that the only session-related information you find in your cookie is a session id, no matter how much information you store in $_SESSION.
04-Jan-2005 01:09
You can't turn off session.use_trans_sid on an individual script basis until PHP5.
However, if you use ini_set('url_rewriter.tags', ''); at the top of your script this will stop the SID being written to the URL's in PHP4.
Hopefully will save someone else a frustrating couple of hours.
Trev
20-Dec-2004 03:27
The session support does not use the IP address for validation. It is based on cookies and URL rewriting.
The reason you lose your session when closing your browser and reconnecting to your ISP (so you are changing your IP), is that sessions are only valides for the visit on your web site, not more.
Changing your IP address will not affect your session except if you close your browser.
23-Nov-2004 02:04
If you are trying to share sessions across a cluster of servers, and don't want to use NFS, or a relatively heavy and slow RDBMS, there is an excellent tool called ShareDance that can do it over a simple TCP protocol. ShareDance comes complete with a PHP interface example and works 'out of the box' for me.
http://sharedance.pureftpd.org/
My thanks to Frank Denis for writing this elegant, valuable piece of software.
14-Sep-2004 03:57
Warnings :
session.bug_compat_42 and bug_compat_warn
Warnings may appears even if your code is correct,
because some asumptions of the developpers.
In practice, these warnings are automatic when your code results in something like:
$_SESSION['var']= NULL;
That is, the code assume that the programmer tried
to assign a unavailable (=NULL) variable because
register_globals is off.
Solution: assign anything but NULL. For example:
$_SESSION['var']= is_null($var) ? 0 : $var;
10-Sep-2004 09:02
Although this IS mentioned in the PHP manual, it is not very clear and can lead to some very hard to track down bugs.
When REGISTER_GLOBALS is ON on a server, local variables of the same name as a session variable can leak their values into the session during a POST or GET.
For example, if you run script "SESS_TEST1.PHP" below, the local var $animal will bleed its value of "I am an Elephant" into the session variable $_SESSION['animal'], which should have a value of "I am a Monkey". Beware!
<?php
// SESS_TEST1.PHP
session_start();
$_SESSION['animal'] = 'I am a Monkey';
$animal = 'I am an Elephant';
$value = 249;
echo "<script>window.location=\"sess_test2.php".
"?animal=$animal&value=$value\"</script>";
?>
<?php
// SESS_TEST2.PHP
session_start();
$animal = $_REQUEST['animal'];
$value = $_REQUEST['value'];
echo "SESSION['animal'] = ".$_SESSION['animal']." (should say \"I am a Monkey\")<br/>";
echo "\$animal = ".$animal."<br/>";
echo "\$value = ".$value."<br/>";
?>
03-Sep-2004 03:06
Be careful when using the Content-Length header with session.use_trans_sid enabled. Technically, it might not be a bug, but PHP does not update the header when it adds the session ID to links in a page. The result is that only partial content is shown in a browser.
In short: if you use ob_get_length to figure out Content-Length, turn session.use_trans_sid off!
18-Aug-2004 12:55
A common problem with session.auto_start, when activated in php.ini file, is the fact that if you've php objects inside the session classes must be loaded before session in started. You'll run into trouble then...
To avoid this, if you cannot ask your sysadmin to modify the php.ini file, add this line to your .htaccess wherever you need it in your application (usually on top of your app):
php_value session.auto_start 0
24-Jun-2004 05:24
[Quote]
Someone posted a message here saying you should just all use the MM shared memory management for sessions. I'd like to CAUTION EVERYONE against using it!
I run a few webservers for a webhosting company, and we quickly ran in to PHP pages segfaulting Apache for unknown reasons, until we did a test with sessions. It turns out that the sessions, while using the mm stuff, couldn't keep the data right. I guess it was to do with the file locking issue mentioned in the documentation here (I didn't notice this until now!).
Anyways, if you run a Unix machine that can map virtual memory to a mount point (like tmpfs or shm or whatever it may be called), use this instead. It's volatile like mm, but works. Only thing you don't get is hidden session info so that other people don't know how to open it easily - but it's better than trying to use mm and having the webserver crash all the time!
[EndQuote]
You're totally right, in my server (FreeBSD 5.2) when using mm to handle sessions, dotProject wouldn't even start, it crashed when accessing index.php. This was solved by creating a swap-backed memory disk with the following options
rw,-s60000,,-b=4096,-f=512,-i=560,-c=3,-m=0,nosuid,nodev,nosymfollow
06-Jun-2004 08:10
sessions not sticking and cookies not setting with IE? took me ages to find the problem.
you need a 'compact privacy policy'! it's not hard once you know how!
this was too much for me: http://www.w3.org/TR/P3P/
but http://www.sitepoint.com/article/p3p-cookies-ie6/2 is very easy to apply
and a visit to this site is very worthwhile: http://www.privacycouncil.com/freep3pfix.php
happy PHP to all!
Erich
05-May-2004 04:28
I found a good solution to create a persistent session by storing a persistence flag, ironically, in the session itelf. I start the session (which sends a Set-Cookie with no expiry time), read the flag and then, if the user wants a persistent session, stop and restart the session with the expiry time set using session_set_cookie_params, which then sends a cookie with a good expiry time. This solution has been quickly tested with all major browsers and seems to work.
I have outlined the whole process in my blog: http://aftnn.org/journal/508
20-Nov-2003 05:05
Be aware of the fact that absolute URLs are NOT automatically rewritten to contain the SID.
Of course, it says so in the documentation ('Passing the Session Id') and of course it makes perfectly sense to have that restriction, but here's what happened to me:
I have been using sessions for quite a while without problems. When I used a global configuration file to be included in all my scripts, it contained a line like this:
$sHomeDirectory = 'http://my.server.com/one/of/my/projects'
which was used to make sure that all automatically generated links had the right prefix (just like $cfg['PmaAbsoluteUri'] works in phpMyAdmin). After introducing that variable, no link would pass the SID anymore, causing every script to return to the login page. It took me hours (!!) to recognize that this wasn't a bug in my code or some misconfiguration in php.ini and then still some more time to find out what it was. The above restriction had completely slipped from my mind (if it ever was there...)
Skipping the 'http:' did the job.
OK, it was my own mistake, of course, but it just shows you how easily one can sabotage his own work for hours... Just don't do it ;)
05-Feb-2003 03:14
Be careful when using ini_set to change the session.gc_maxlifetime value locally for your script:
You will trash other people's sessions when garbage collection takes place (and they will trash yours) regardless of their (your) intended session.gc_maxlifetime, because the session_name is not taken into account during garbage collection.
Create an own directory and set session.save_path to it, so that your session files don't get mixed.
13-Oct-2002 07:43
If you have problem to download a file from your PHP , and you have IE (any version) and apache for server with SSL, check the reference of: session-cache-limiter
My best solution is change the php.ini from
session.cache_limiter = nocache
to:
session.cache_limiter = private, must-revalidate
15-May-2002 03:34
Storing class instances in session.
As long as a class MUST be declared BEFORE the session starts and unserializes the session info, i'm using this approach.
0: Set in php.ini session.auto_start = 0
1: create myclass.inc where the class is declared.
2: put in another file, say header.inc, this lines of code:
include_once( "myclass.inc" );
session_start();
3: set in php.ini the auto_prepend_file= "path_to_my_file/header.inc"
Following this steps, the session is started at every page and myclass is always available, avoiding to write the session_start() function at every page.
16-Oct-2000 09:16
Regarding session.cache_limiter :
For those of you who - like me - had trouble finding the meaning of the possible values (nocache, public and private), here's the explaination taken from the HTTP 1.1 Specification at
http://www.w3.org/Protocols/rfc2068/rfc2068
"14.9.1 What is Cachable
[snip]
public
Indicates that the response is cachable by any cache, even if it would normally be non-cachable or cachable only within a non-shared cache. (See also Authorization, section 14.8, for additional details.)
private
Indicates that all or part of the response message is intended for a single user and MUST NOT be cached by a shared cache. This allows an origin server to state that the specified parts of the response are intended for only one user and are not a valid response for requests by other users. A private (non-shared) cache may cache the response.
Note: This usage of the word private only controls where the response may be cached, and cannot ensure the privacy of the message content.
no-cache
Indicates that all or part of the response message MUST NOT be cached anywhere. This allows an origin server to prevent caching even by caches that have been configured to return stale responses to client requests.
Note: Most HTTP/1.0 caches will not recognize or obey this directive."
20-Aug-2000 11:11
Session Garbage Collection Observation:
It appears that session file garbage collection occurs AFTER the current session is loaded.
This means that:
even if session.gc_maxlifetime = 1 second,
if someone starts a session A and no one starts a session for an hour, that person can reconnect to session A and all of their previous session values will be available (That is, session A will not be cleaned up even though it is older than gc_maxlifetime).