session_regenerate_id

(PHP 4 >= 4.3.2, PHP 5, PHP 7)

session_regenerate_id 現在のセッションIDを新しく生成したものと置き換える

説明

session_regenerate_id ([ bool $delete_old_session = FALSE ] ) : bool

session_regenerate_id() は現在のセッションIDを 新しいものと置き換えます。その際、現在のセッション情報は維持されます。

session.use_trans_sid が有効な場合は、 session_regenerate_id() を呼んでから出力を始めないといけません。 それ以前の出力には、古いセッション ID が使われます。

警告

現在の session_regenerate_id は、不安定なネットワークをうまく扱えません。 たとえば、モバイルネットワークや WiFi ネットワークです。 よって、 session_regenerate_id を 呼ぶことで、セッションの消失を経験するかもしれません。

すぐに古いセッションデータを破棄すべきではありませんが、 古いセッションID のタイムスタンプと、 アクセス制御は破棄すべきでしょう。 さもないと、ページへの同時アクセスによって、 状態の不整合が発生したり、セッションが失われたり、 クライアント(ブラウザ) 側のレースコンディションが発生したり、 不必要なセッションIDをたくさん作らなければならなくなるかもしれません。 セッションデータをすぐに破棄してしまうと、 セッションハイジャックの検出だけでなく、 防止もできなくしてしまいます。

パラメータ

delete_old_session

関連付けられた古いセッションを削除するかどうか。 削除による競合を防いだり、セッションハイジャックを 検出/防ぐ 必要がある場合には、古いセッションを削除すべきではありません。

返り値

成功した場合に TRUE を、失敗した場合に FALSE を返します。

変更履歴

バージョン 説明
7.0.0 session_regenerate_id() 関数は、 終了する前に古いセッションデータを保存するようになりました。
5.1.0 delete_old_session パラメータが追加されました。

例1 session_regenerate_id() の使用例

<?php
// 注意: このコードは完全に動作するわけではありません。一例です!

session_start();

// 破棄されたタイムスタンプをチェック
if (isset($_SESSION['destroyed'])
    && 
$_SESSION['destroyed'] < time() - 300) {
    
// 通常は起こるべきではない。攻撃や不安定なネットワークによる可能性がある
    // このユーザーのセッションから、全ての認証ステータスを削除
    
remove_all_authentication_flag_from_active_sessions($_SESSION['userid']);
    throw(new 
DestroyedSessionAccessException);
}

$old_sessionid session_id();

// 破棄されたタイムスタンプを設定
$_SESSION['destroyed'] = time(); // PHP 7.0.0 以降では、session_regenerate_id() は古いセッションデータを保存します。

// 単に session_regenerate_id() を呼ぶだけでは、セッションの消失などに繋がる可能性があります。
// 次の例を見てください。
session_regenerate_id();

// 新しいセッションには、破棄されたタイムスタンプは不要
unset($_SESSION['destroyed']);

$new_sessionid session_id();

echo 
"古いセッション: $old_sessionid<br />";
echo 
"新しいセッション: $new_sessionid<br />";

print_r($_SESSION);
?>

現在のセッションモジュールは、不安定なネットワークをうまく扱えません。 session_regenerate_id によるセッションの消失を避けるために、 セッションIDを管理すべきです。

例2 session_regenerate_id() による、セッションの消失を避ける

<?php
// 注意: このコードは完全に動作するわけではありません。一例です!
//  my_session_start() and my_session_regenerate_id() によって、
//  不安定なネットワークによるセッションの消失を避けています。
//  それに加えて、このコードは攻撃者から、盗まれたセッションを利用した
//  攻撃を防ぐ可能性もあります。

function my_session_start() {
    
session_start();
    if (isset(
$_SESSION['destroyed'])) {
       if (
$_SESSION['destroyed'] < time()-300) {
           
// 通常は起こるべきではない。攻撃や不安定なネットワークによる可能性がある
           // このユーザーのセッションから、全ての認証ステータスを削除
           
remove_all_authentication_flag_from_active_sessions($_SESSION['userid']);
           throw(new 
DestroyedSessionAccessException);
       }
       if (isset(
$_SESSION['new_session_id'])) {
           
// 完全に expire してはいない。
           // Cookie が不安定なネットワークによって失われた可能性がある。
           // 適切なセッションIDのクッキーを設定するためにリトライする。
           // 注意: 認証フラグを削除したい場合は、セッションIDを再度設定しようとしてはいけない。
           
session_commit();
           
session_id($_SESSION['new_session_id']);
           
// 新しいセッションIDが存在しているはず
           
session_start();
           return;
       }
   }
}

function 
my_session_regenerate_id() {
    
// 不安定なネットワークのために、セッションID が設定されなかったときは、
    // 新しいセッションID が、適切なセッションIDに設定されることが必須。
    
$new_session_id session_create_id();
    
$_SESSION['new_session_id'] = $new_session_id;
    
    
// 破棄された時のタイムスタンプを設定
    
$_SESSION['destroyed'] = time();
    
    
// 現在のセッションを書き込んで閉じる
    
session_commit();

    
// 新しいセッションを新しいセッションIDで開始
    
session_id($new_session_id);
    
ini_set('session.use_strict_mode'0);
    
session_start();
    
ini_set('session.use_strict_mode'1);
    
    
// 新しいセッションには、以下の情報は不要
    
unset($_SESSION['destroyed']);
    unset(
$_SESSION['new_session_id']);
}
?>

参考

  • session_id() - 現在のセッション ID を取得または設定する
  • session_create_id() - 新しいセッションIDを作成する
  • session_start() - 新しいセッションを開始、あるいは既存のセッションを再開する
  • session_destroy() - セッションに登録されたデータを全て破棄する
  • session_reset() - session 配列を元の値で再初期化します
  • session_name() - 現在のセッション名を取得または設定する