web-dev-qa-db-ja.com

PHPでのセッションタイムアウト:ベストプラクティス

_session.gc_maxlifetime_とsession_cache_expire()の実際の違いは何ですか?

非アクティブな状態が15分間続いた後にユーザーセッションを無効にしたいとします(最初に開いた後は15になりません)。これらのうちどれが私を助けますか?

また、ユーザーのCookieを一定の時間で期限切れに設定できるsession_set_cookie_params()を実行できることも知っています。ただし、Cookieの有効期限とサーバー側で有効期限が切れる実際のセッションは同じではありません。これにより、Cookieの有効期限が切れたときにセッションも削除されますか?

私が考えている別の解決策は、すべての要求に対して単純な$_SESSION['last_time'] = time()を使用し、セッションを現在の時刻と比較して、それに基づいてセッションを削除することです。これを処理するためのより「組み込みの」メカニズムがあることを望んでいました。

ありがとう。

35
Chad

session_start が呼び出されるたびに、セッションファイルのタイムスタンプ(存在する場合)が更新されます。これは、session.gc_maxlifetimeを超えているかどうかの計算に使用されます。

さらに重要なのは、session.gc_maxlifetimeの時間を超えた後にセッションを期限切れにすることはできません。

PHPは、現在のセッションが読み込まれた後、有効期限が切れたセッションでガベージコレクションを実行し、 session.gc_probability および session.gc_divisor を使用して、ガベージコレクションが実行される確率を計算します。デフォルトでは、1%の確率です。

訪問者の数が少ない場合、非アクティブなユーザーが、期限切れで削除されているはずのセッションにアクセスできる可能性があります。これが重要な場合は、セッションにタイムスタンプを保存し、ユーザーが非アクティブであったログを計算する必要があります。

この例は session_start を置き換え、タイムアウトを強制します。

function my_session_start($timeout = 1440) {
    ini_set('session.gc_maxlifetime', $timeout);
    session_start();

    if (isset($_SESSION['timeout_idle']) && $_SESSION['timeout_idle'] < time()) {
        session_destroy();
        session_start();
        session_regenerate_id();
        $_SESSION = array();
    }

    $_SESSION['timeout_idle'] = time() + $timeout;
}
40
Glass Robot

Php.iniサーバーの設定がセッションを期限切れにする方法に対する良い答えを探すために、少し時間を費やしました。たくさんの情報を見つけましたが、なぜ設定が機能するのかを理解するのにしばらく時間がかかりました。あなたが私のような人なら、これはあなたに役立つかもしれません:

セッションはCookie(クライアントのPC上のファイル)またはサーバー側のファイルとしてサーバーに保存されます。どちらの方法にも長所と短所があります。

サーバーに保存されているセッションでは、3つの変数が使用されます。

session.gc_probability session.gc_divisor session.gc_maxlifetime

(session.gc_probability/session.gc_divisor)は、ガベージコレクションルーチンが実行される確率を生成します。ガベージコレクターが実行されると、少なくともsession.gc_maxlifetimeの間アクセスされていないセッションファイルがチェックされ、削除されます。

これはすべてフォーラムの投稿でかなりよく説明されています(特にこれは!)-しかし、次の質問が浮かび上がります:

1.)その確率はどのように適用されますか?サーバーはいつサイコロを振るのですか?

A:サーバーは、サーバー上のアクティブなセッション中にsession_start()が呼び出されるたびにサイコロを振ります。つまり、これは、デフォルトのsession.gc_probability = 1およびsession.gc_divisor = 100の場合、session_start()が呼び出されるほぼ100回ごとにガベージコレクターが実行されることを意味します。

2.)少量のサーバーで何が起こりますか?

A:session_start()が呼び出されると、最初にセッションが更新され、セッション値が利用可能になります。これにより、サーバー上のセッションファイルの時間が更新されます。その後、サイコロを振り、勝った場合(100分の1の確率)、ガベージコレクターを呼び出します。次に、ガベージコレクターはすべてのセッションIDファイルをチェックし、削除に適格なものがあるかどうかを確認します。

つまり、サーバー上の唯一のユーザーである場合、セッションが非アクティブになることはなく、設定を変更しても効果がないように見えます。 session.gc_maxlifetimeを10に、session.gc_probabilityを100に変更するとします。これは、ガベージコレクターが実行される可能性が100%あり、過去10秒間アクセスされていないセッションファイルがすべて消去されることを意味します。

サーバー上で唯一のユーザーである場合、セッションは削除されません。セッションを非アクティブにするには、少なくとも1つのアクティブなセッションを実行する必要があります。

したがって、基本的には、少量のサーバーまたは少量の時間-ガベージコレクターが実際に実行されてセッションが実際に削除されるまでの時間は、session.gc_maxlifetimeよりはるかに長くなる可能性があります。そして、これがどのように機能するかを知らなければ、完全にランダムに見えるかもしれません。

3.)なぜ確率を使用するのですか?

パフォーマンス。ボリュームの大きいサーバーでは、session_start()のすべてのリクエストでガベージコレクターを実行する必要はありません。サーバーを不必要に遅くします。そのため、サーバーのボリュームに応じて、ガベージコレクターが実行される確率を増減することができます。

これがあなたのために物事を結びつけることを願っています。私と同じようにsession.gc_maxlifetimeを試してもうまくいかなかった場合は(だれも邪魔しないように開発サーバーで試してみたため)、この投稿で頭を悩ませることができれば幸いです。

幸運を!

56
Be_Open

session.gc_maxlifetimeは、セッションファイルが最後に変更された時刻に基づいています。そのため、セッションファイルが変更されるか、別のページでsession_start()が呼び出されるたびに、gc_maxlifetimeへのカウントダウンが新たに始まり、ユーザーは「ログイン」したままになります。これがあなたが求めている価値です。これを変更するには、phpファイルのini_set()を使用するか、アクセス権がある場合はphp.iniを編集します。

session_cache_expire()は、HTTP "Expires"ヘッダーのみを制御します。このヘッダーは、ダウンロードされたページのコンテンツがユーザーのブラウザーキャッシュに保持される期間を制御します。

6
Mark

現在の値を確認するには、次のコードが役立ちます。

$gc_maxlifetime = ini_get('session.gc_maxlifetime');
$gc_probability = ini_get('session.gc_probability');
$gc_divisor     = ini_get('session.gc_divisor');
1
NXT