3

今日セッション ライブラリを修正しているときに問題が発生しました。バック エンド スクリプトでブラウザ固有の問題を見たのはこれが初めてかもしれません。誰かが光を当てることができることを願っています。

基本的に、セッション ライブラリの仕組みは次のとおりです。インスタンス化されると、クライアント マシンで「id」と呼ばれる Cookie を (uniqid 結果の形式で) チェックします。Cookie が見つかった場合、スクリプトはそれとユーザー エージェント文字列のハッシュ化されたコピーをセッション テーブルのエントリと照合します。一致するエントリが見つかった場合、スクリプトはセッションを再開します。「id」という名前の Cookie が見つからない場合、またはセッション テーブルに一致するエントリが存在しない場合、スクリプトは両方を作成します。かなり標準的だと思います。

ここで奇妙な点があります。Firefox では、すべてが予測どおりに機能します。ユーザーは 1 つのセッションを取得し、非アクティブ状態が 24 時間経過しない限り、接続時に常に再開されます。しかし、Chrome でページにアクセスすると、同じように見え、同じ順序でクエリを実行しているように見えますが、セッション テーブルに 2 つのエントリが表示されます。セッションはエージェント文字列を共有しますが、ID は異なります。タイムスタンプ ログは、ユーザー用に作成されたセッションの直後 (1 秒以内) にゴースト セッションが作成されていることを示しています。

デバッグの目的で、実行時にクエリを画面に出力してきました。これは、Chrome が 1 つのセッションを開く必要があり、代わりに 2 つのセッションを開いているときに表示される例です。

// Attempting to resume a session
SELECT id FROM sessions WHERE id = '4fd24a5cd8df12.62439982' AND agent = '9bcd5c6aac911f8bcd938a9563bc4eca'

// No result, so it creates a new one
INSERT INTO sessions (id, agent, start, last) VALUES ('4fd24ef0347f26.72354606', '9bcd5c6aac911f8bcd938a9563bc4eca', '1339182832', '1339182832')

// Clear old sessions
DELETE FROM sessions WHERE last < 1339096432

その後、データベースに表示されるのは次のとおりです。

id, agent, start, last
4fd24ef0347f26.72354606, 9bcd5c6aac911f8bcd938a9563bc4eca, 1339182832, 1339182832
4fd24ef0857f94.72251285, 9bcd5c6aac911f8bcd938a9563bc4eca, 1339182833, 1339182833

明らかな何かが欠けていますか?私が考えられる唯一のことは、Chrome がバックグラウンドで非表示のセッションを作成し、ページをクロールしている可能性があるということです。ただし、その場合は、アクティブなセッションを users テーブルのエントリに関連付け始めるときに、後で問題になる可能性があります。スクリプトの潜在的なバグを探していましたが、これまでのところ何も見つかりませんでした。すべてが Firefox で期待どおりに機能します。

4

1 に答える 1

4

私は以前にこれに遭遇したことがあり、同様に混乱していました。数か月前から、Chromeではプリフェッチが有効になっています。そのため、ユーザーに認識される速度を上げるために、ページ上のほとんどのリンクをクロールし、それらを部分的に事前に取得してレンダリングします。ブロードバンドを使用している場合は、ページの変更時間を大幅に短縮できるため、エンドユーザーに最適です。

私たちWeb開発者にとって残念なことに、それは上記のような混乱につながります。これは、たとえばChromeユーザーがWebサイトにアクセスし、Cookieまたはセッションがまだ割り当てられていないが、ブラウザーが複数のページをプリフェッチし、複数のセッションが割り当てられている場合に発生します。

たとえば、誰かがPHPスクリプトのさまざまな領域へのリンクがあるページにアクセスし、スクリプトがすべての訪問者にCookieを割り当てるように設計されているとします... Chromeがそれらのページの2つを同時にまたはそれに近いものをフェッチすると、PHPは最終的にChromeの別のスレッドは基本的に、他の割り当てが完了する前に新しいセッション/ Cookieを必要とするため、異なるセッション。

私が知っている解決策は2つあります。1つは事前レンダリングを処理するためのGoogleのJavaScriptAPIですが、これは特に優れているとは思いませんでした。もう1つの方法は、PHPからセッションとCookieを配布するときに、より厳密なチェックを実行することです。ゲストユーザーにセッションを割り当てないか、いくつかのチェック(IP、ホスト名など)を追加します。

お役に立てば幸いです。

于 2012-06-20T15:13:14.977 に答える