HOWTO · PHP
PHP でセッションタイムアウトを設定する
PHPで、最後のリクエストから30分間操作がない場合にセッションタイムアウトを適用する方法を解説します。
このページの内容
PHPでは、指定した時間操作がなくても、アプリケーションのセッションが自動的に期限切れになるわけではありません。30分のタイムアウトを適用するには、最後のリクエスト時刻を $_SESSION に保存し、リクエストごとに現在時刻と比較して、差が1,800秒以上になったら処理します。タイムアウトが検出されるのは、アイドル期間の後に次のリクエストが届いたときです。ブラウザーからリクエストが途絶えた瞬間に、サーバーが処理を実行することはできません。
PHPのセッションタイムアウトを追跡する
session_start() を呼び出してから、$_SESSION を読み取ったり変更したりします。最初のリクエストでは、保存済みのアクティビティ時刻がないため、初期化します。以降のリクエストでは、保存した時刻を time() と比較します。1,800秒の上限に達していたらセッションデータを消去してリクエストを終了し、達していなければアクティビティ時刻を更新して、30分間の計測を再開します。
次の例を実行します。
このセクションのコードと表示されるラベルや出力は英語のままです。
<?php
session_start();
$timeoutSeconds = 30 * 60;
$now = time();
if (isset($_SESSION['last_activity']) &&
$now - $_SESSION['last_activity'] >= $timeoutSeconds) {
session_unset();
session_destroy();
echo "Session expired" . PHP_EOL;
exit;
}
$_SESSION['last_activity'] = $now;
echo "Session active" . PHP_EOL;
Session active
最初のリクエストでは last_activity が初期化され、アクティブな場合の処理に進みます。以降のリクエストでは、時刻を更新する前に直前のタイムスタンプを確認します。提供された実行エビデンスでは、アクティブな場合に Session active と表示され、終了コードは0です。この結果には、期限切れの場合の実行は含まれていません。アプリケーションでは、session_start() の後、認証が必要な処理の前にこのチェックを行い、期限切れのリクエストを認証済みとして処理しないようにします。
30分間操作がなければセッションを破棄する
タイムアウトに達したとき、この例では session_unset() と session_destroy() の両方を使用します。session_unset() は現在のセッション変数を消去し、session_destroy() は有効なセッションハンドラーが保存しているセッションデータを削除します。サーバー側のデータを破棄しても、ブラウザーのセッションCookieが自動的に削除されるわけではありません。Cookieも期限切れにする必要がある場合は、同じ名前、パス、ドメインの設定を使って、期限切れのCookieを送信します。Cookieの扱いはアプリケーションのセッション設定によって異なります。
これはアプリケーション側で行うタイムアウトです。チェックを実行するコードにリクエストが届いたときにのみ動作します。PHPのセッションストレージ有効期間の設定は、ストレージのクリーンアップを制御するもので、リクエストごとの非アクティブ判定とは別です。PHPマニュアルの session_unset() の説明とセッション設定オプションを参照してください。
unset()でセッション変数を削除する
unset($_SESSION['cart']) を使うと、ほかのセッション項目を残したまま、1つの項目だけを削除できます。セッション全体を終了せずに、カートのような特定の状態をユーザーが削除する場合に適しています。この操作だけでは、非アクティブタイムアウトは実装されません。関連する値をまとめて扱う場合は、配列のキーの下に保存し、unset($_SESSION['account_state']) でそのキーだけを削除します。後続のタイムアウトチェックが registered 要素を参照するなら、その配列をタイムスタンプで置き換えないでください。
スーパーグローバル変数 $_SESSION は、session_start() の後に使用できます。PHPマニュアルの $_SESSION の説明を参照してください。
タイムアウト処理とは別にセッションIDを再生成する
session_regenerate_id() は現在のセッション識別子を置き換えます。非アクティブ時間を測定したり、セッションデータを破棄したり、ユーザーに自動的に再ログインを要求したりする関数ではありません。タイムアウトチェックとは別に、アプリケーションの認証フローに適したタイミングで、識別子をローテーションする方針に使います。古いセッションデータが保持されるかどうかは、関数のオプションとセッション処理に依存します。そのため、IDの再生成だけでログアウトになる、あるいは以前の識別子が使えなくなると判断しないでください。
session_id() 関数は現在の識別子を読み取り、session_start() はリクエストに関連付けられたセッションを再開します。詳しくはPHPマニュアルの session_regenerate_id() の説明とsession_id() 関数を参照してください。