web-dev-qa-db-ja.com

ユーザーが同じセッションで2つのタブを開いたかどうかを検出するにはどうすればよいですか?

私はCakePHPを使用して行われた予約アプリケーションを実行しました。これには、チェックアウトページの数ステップ前が含まれます。これらのステップの間に、セッションに情報を保存します。

それがどのように機能するかは、ステップ1が彼らに彼らの情報を記入することを要求するということです。手順2に進むと、手順1の情報がセッションオブジェクトに保存されます。他のステップに進むと、プロセスが繰り返されます。チェックアウトの最後に、すべてのデータがデータベースに保存されます。

ユーザーがブラウザでアプリケーションの1つのインスタンスを開くと、すべてがうまく機能します。ただし、同じブラウザで同じアプリケーションに対して別のページまたは別のタブを開くと、問題が発生します。

アプリケーションの2つのインスタンスがタブAとタブBで開いているとします。タブAで、ステップ1で詳細を入力し、ステップ2に進みます。次に、ユーザーはタブBで同じことを行います。

ユーザーがチェックアウトを行う最後のステップで、タブAの情報はタブBの情報と同じです。

今のところ、最善の方法は、ユーザーが2つのブラウザインスタンスで同じアプリケーションを開かないようにすることだけだと思います。

ユーザーがタブBで別のインスタンスを開こうとしたときに、最初にタブAの予約フォームに記入するようにユーザーを検出して促す方法はありますか?

18
darnpunk

1.同じ問題(および解決策): https://sites.google.com/site/sarittechworld/track-client-windows

2. POSTまたはGETで情報を送信できます

9
pufos

もちろん、これはクライアント側のポーラースクリプトで実現できます。 JavaScriptでは、一意であることが保証されている限り、任意のウィンドウIDを生成できます。 JSに、IDとセッションを比較するだけのサーバー上のエンドポイントへのAjax呼び出し元を作成させます。 2つの異なる「windowID」値がある場合はいつでも、同じセッションでウィンドウを開く必要があることがわかります。

これをサーバー側でセッションの配列として保存することも、クライアント側で完全にCookieに保存することもできます。これを選択した場合、クライアント側のポーラーはCookieの値を確認するだけで、2つの異なる値が含まれている場合は、何かがおかしいです。ただし、Cookieは要求/応答サイクルに重みを加え、ユーザーがページをアンロードしたときに現在のページの値をクリアするメカニズムを設定する必要があるため、少し理想的ではありません。

サーバー側の実装では、サーバーがセッションからwindowIDをクリアできるように、リンクまたは投稿とともに現在のwindowIDを送信する必要があります。ただし、FirefoxセッションとChromeセッションを同時に開いているユーザーを防ぐことはできません。

2
Jackson Gabbard

ステップ1が最初に開始されたときに、セッションを開始済みとしてマークできます。サーバー側が正しい手順に従っていることを確認します(つまり、特にリンクをクリックしない限り、手順1の完了後に手順1に戻らない)。基本的に、サーバー上の現在の手順を追跡して更新します。必要に応じて。ユーザーが予期しないことをした場合は、最初からやり直すオプションをユーザーに与えることができます。

フォームにタイムスタンプが付いた非表示のフィールドが役立つかどうか疑問に思っています。ちょっと同じ考えです。

警告:このプロセスは、ブラウザの戻るボタンの本質を壊す可能性があります。私は自分のプロジェクトの1つでそれを起こさせるのが嫌いです。

クロスブラウザをサポートするには、ユーザーアカウントまたは永続的なものに関連付ける必要があります。

2
Guttsy

ベンジャミンが指摘したように、これを行うには、ウィンドウごとのIDを考え出し、それをリクエストごとにサーバーに報告します。複数ウィンドウのユースケースを有効にしたい場合は、これが最も合理的なアプローチだと思います。

ただし、これを行うためにajaxを介してサーバーをポーリングする必要はないと思います。サーバーへのすべてのリクエストにウィンドウIDが含まれている限り、サーバー側でリクエストを関連付けるセッションを明確にすることができます。つまり、サーバー側のコードを変更して、セッションの一部としてウィンドウIDを含める必要があります。

ただし、そのアプローチには重大な欠点があります。たとえば、ユーザーがタブAとタブBの両方を閉じてから、新しいタブCを開いた場合、どうなりますか?どのデータセットに再接続する必要がありますか?

状態に相当する複数のタブが混在するのを防ぐ必要がある場合、ユーザーを単一のタブに制限するアプローチはかなり合理的に聞こえます。

ところで、ローカルストレージを介してこれを行うことができます。クライアントでランダムIDを生成し、window.localStorage.setItem('window_id', <my_random_id_here>);などの呼び出しを介してローカルストレージにプッシュすると、ページの読み込み時にこの値を確認できます。ページの読み込み時に値が存在する場合は、少なくとも1つの他のウィンドウが開いていることを示す非常に明確なインジケーターがあります。ページのアンロード時にこの値を必ず削除する必要があります。そうしないと、セッションのデッドが誤検知を引き起こす可能性があります。

0
Jackson Gabbard