既知の効果的な方法は、session_set_save_handler を使用してすべてのセッション管理作業を引き継ぐことです。一般に、セッション情報はデータベースに保存されるため、SQL ステートメントを通じて期限切れのセッションをすべて削除でき、セッションの有効期間を正確に制御できます。 。これは、PHP ベースの大規模な Web サイトで一般的に使用される方法でもあります。ただし、通常の小規模な Web サイトの場合は、それほど苦労する必要はないようです。
ただし、一般的なセッションの有効期間は限られており、ユーザーがブラウザを閉じると、セッション変数は保存できません。では、Session の永続的な寿命を達成するにはどうすればよいでしょうか?
ご存知のとおり、セッションはクライアントから提供されたセッション ID に基づいてサーバー側に保存され、そのファイルはクライアントの Cookie または変数の値を取得するために読み取られます。アクセスされたHttp1.1プロトコルのQuery_String(URLの「?」以降の部分)がサーバーに送信され、サーバーはSessionのディレクトリを読み込みます...
永続化を実現するにはセッションについては、まず php.ini のセッションの関連設定を理解する必要があります (php.ini ファイルを開き、「[セッション]」セクションにあります):
1. session.use_cookies: デフォルト値は「1」です。これは、SessionID が Cookie によって渡されることを意味します。それ以外の場合は、Query_String によって渡されます。
2. session.name: ここに、SessionID が格納されます。デフォルト値は、Cookie または Query_String です。 3. session.cookie_lifetime: これは、セッション ID がクライアント Cookie に保存される時間を表します。デフォルトは 0 です。これは、ブラウザがセッション ID を閉じることを意味します。このため、セッションは永続的に使用できません。
4. session.gc_maxlifetime: セッション データがサーバー側に保存される時間です。この時間を超えると、セッション データは自動的に削除されます。
他にも多くの設定がありますが、これらはこの記事に関連するものです。まず、永続セッションを使用するための原則と手順から始めましょう。
前に述べたように、サーバーは SessionID を介してセッション データを読み取りますが、通常、ブラウザによって送信された SessionID はブラウザを閉じると失われます。その場合は、SessionID を手動で設定して保存するだけで済みます。これは、サーバーの操作権限に依存するため、次の手順を実行するだけで非常に簡単です。
1. 「session.use_cookies」を 1 に設定し、SessionID を保存するための Cookie をオンにします。 1. 通常は変更する必要はありません。
2. 「session.cookie_lifetime」を正の無限大に変更します (もちろん、正の無限大のパラメーターはありませんが、999999999 と正の無限大を設定します)。 session.gc_maxlifetime" を "session.cookie_lifetime" と同じ時間にします ;
セッションの有効期間を設定するパラメータは session.gc_maxlifetime であることが PHP ドキュメントに明記されています。このパラメータは、php.ini ファイルまたは ini_set() 関数を通じて変更できます。問題は、多くのテストを行った後、このパラメーターを変更しても基本的には効果がなく、セッションの有効期間がデフォルト値の 24 分のままであることです。
PHP の動作メカニズムにより、セッション情報を定期的にスキャンして、セッション情報が無効かどうかを判断するデーモン スレッドがありません。有効なリクエストが発生すると、PHP はグローバル変数 session.gc_probability/session.gc_divisor (php.ini または ini_set() 関数を通じて変更することもできます) の値に基づいて GC (ガベージ コレクター) を開始するかどうかを決定します。 。デフォルトでは、session.gc_probability = 1、session.gc_divisor = 100 です。これは、GC が開始される確率が 1% であることを意味します。
GC の仕事は、すべてのセッション情報をスキャンし、現在の時刻からセッションの最終変更時刻 (変更日) を減算し、それを session.gc_maxlifetime パラメーターと比較し、生存時間が gc_maxlifetime を超えている場合は、セッションを削除することです。 。
これまでのところ、すべてが正常に動作しています。では、なぜ gc_maxlifetime が無効になるのでしょうか?
デフォルトでは、セッション情報はシステムの一時ファイルディレクトリにテキストファイルの形式で保存されます。 Linux では、このパスは通常 tmp であり、Windows では通常 C:WindowsTemp です。サーバー上に複数の PHP アプリケーションがある場合、それらのセッション ファイルは同じディレクトリに保存されます。同様に、これらの PHP アプリケーションも一定の確率で GC を開始し、すべてのセッション ファイルをスキャンします。
問題は、GC が動作しているときに、異なるサイト上のセッションが区別されないことです。たとえば、サイト A の gc_maxlifetime は 2 時間に設定され、サイト B の gc_maxlifetime はデフォルトの 24 分に設定されます。サイト B の GC が開始されると、パブリック一時ファイル ディレクトリがスキャンされ、サイト A からのものかサイト B からのものかに関係なく、24 分より古いすべてのセッション ファイルが削除されます。このように、サイト A の gc_maxlifetime 設定は役に立ちません。
問題を見つけたら、解決するのは簡単です。 session.save_path パラメータを変更するか、session_save_path() 関数を使用して、セッションが保存されるディレクトリを専用のディレクトリに指定します。 gc_maxlifetime パラメータは正常に機能します。
厳密に言うと、これは PHP のバグですか?
もう 1 つの問題は、gc_maxlifetime が保証できるのはセッションの存続時間の最短時間だけであり、この時間を過ぎるとセッション情報はすぐに削除されることです。 GC は確率に基づいて開始され、長期間開始されない可能性があるため、gc_maxlifetime を超えた後も多数のセッションが有効になります。この問題を解決する 1 つの方法は、session.gc_probability/session.gc_divisor の確率を 100% まで高めることです。ただし、この問題は明らかにパフォーマンスに重大な影響を及ぼします。もう 1 つの方法は、コード内で現在のセッションの存続期間を確認し、それが gc_maxlifetime を超えた場合は、現在のセッションをクリアすることです。
ただし、サーバーを操作する権限がない場合は、永続的なセッション データの保存を実現するために、PHP プログラムを通じて SessionID を書き換える必要があります。 php.net の関数マニュアルを確認すると、「session_id」関数が表示されます。パラメータが設定されていない場合は、現在のセッション ID が返されます。パラメータが設定されている場合は、現在のセッション ID が指定された値に設定されます。
永続的な Cookie を使用し、「session_id」関数を追加する限り、永続的なセッション データを保存できます。
ただし、便宜上、サーバー設定の「session.name」を知る必要がありますが、ほとんどのユーザーはサーバーの php.ini 設定を表示する権限を持っていません。ただし、PHP には非常に優れた関数「phpinfo」が用意されています。ほぼすべての PHP 情報を表示するために使用されます。
------------------------------------------------- ----------------------------------
session_start(); ini_set('session.save_path','/tmp/'); //6个钟头 ini_set('session.gc_maxlifetime',21600); //保存一天 $lifeTime = 24 * 3600; setcookie(session_name(), session_id(), time() + $lifeTime, "/");
実際、Cookieの保存期間は限られており、サーバーの容量も限られているため、真の永久保存は不可能です...しかし、長期間保存する必要がある一部のサイトについては、上記の方法で十分です!
mysql にセッションを入れます 例:
データベースにテーブルを作成します: session (sesskey varchar32, expiry int11, value longtext)
コード:
コードが実行される前にデータベースが接続されています。
define('STORE_SESSIONS','mysql'); if (STORE_SESSIONS == 'mysql') { if (!$SESS_LIFE = get_cfg_var('session.gc_maxlifetime')) { $SESS_LIFE = 1440; } function _sess_open($save_path, $session_name) { // 如果没有连接数据库,可以在此执行mysql_pconnect,mysql_select_db return true; } function _sess_close() { return true; } function _sess_read($key) { $value_query = mysql_query("select value from sessions where sesskey = '" .addslashes($key) . "' and expiry > '" . time() . "'"); $value = mysql_fetch_array($value_query); if (isset($value['value'])) { return $value['value']; } return false; } function _sess_write($key, $val) { global $SESS_LIFE; $expiry = time() + $SESS_LIFE; $value = $val; $check_query = mysql_query("select count(*) as total from sessions where sesskey = '" . addslashes($key) . "'"); $check = mysql_fetch_array($check_query); if ($check['total'] > 0) { return mysql_query("update sessions set expiry = '" . addslashes($expiry) . "', value = '" . addslashes($value) . "' where sesskey = '" . addslashes($key) . "'"); } else { return mysql_query("insert into sessions values ('" . addslashes($key) . "', '" . addslashes($expiry) . "', '" . addslashes($value) . "')"); } } function _sess_destroy($key) { return mysql_query("delete from sessions where sesskey = '" . addslashes($key) . "'"); } function _sess_gc($maxlifetime) { mysql_query("delete from sessions where expiry < '" . time() . "'"); return true; } session_set_save_handler('_sess_open', '_sess_close', '_sess_read', '_sess_write', '_sess_destroy', '_sess_gc'); } danoo_session_name( 'dtvSid' ); danoo_session_save_path(SESSION_WRITE_DIRECTORY);