137

JSP とサーブレットを使用して Java で実装された Web アプリケーション。ユーザー セッションに情報を保存すると、この情報は同じブラウザーのすべてのタブから共有されます。ブラウザタブでセッションを区別する方法は? この例では:

<%@page language="java"%>
<%
String user = request.getParameter("user");
user = (user == null ? (String)session.getAttribute("SESSIONS_USER") : user);
session.setAttribute("SESSIONS_USER",user);
%>
<html><head></head><body>
<%=user %>
<form method="post">
User:<input name="user" value="">
<input type="submit" value="send">
</form>
</body></html>

このコードを jsp ページにコピーし ( testpage.jsp)、サーバー上の Web アプリケーションの既存のコンテキストにこのファイルをデプロイし (私は Apache Tomcat を使用しています)、正しい URL を使用してブラウザー (FF、IE7、または Opera) を開き ( localhost/context1/testpage.jsp)、次のように入力します。あなたの名前を入力して、フォームを送信してください。次に、同じブラウザーで新しいタブを開くと、新しいタブに (セッションから取得した) 自分の名前が表示されます。ブラウザのキャッシュに注意してください。時々発生しないように見えますが、キャッシュにあるので、2 番目のタブを更新してください。

ありがとう。

4

20 に答える 20

96

HTML5 SessionStorage (window.sessionStorage) を使用できます。ランダムな ID を生成し、ブラウザ タブごとにセッション ストレージに保存します。次に、各ブラウザー タブには独自の ID があります。

sessionStorage を使用して保存されたデータは、2 つのタブの両方に同じドメイン オリジンの Web ページが含まれている場合でも、ブラウザーのタブ間で保持されません。つまり、sessionStorage 内のデータは、呼び出し元のページのドメインとディレクトリだけでなく、ページが含まれるブラウザー タブにも限定されます。これを、タブからタブへとデータを保持するセッション Cookie と比較してください。

于 2012-08-02T18:39:35.937 に答える
25

サーバー側のセッションは HTTP への人為的なアドオンであることを認識する必要があります。HTTP はステートレスであるため、サーバーは、リクエストが特定のユーザーに属し、セッションを持っていることを何らかの方法で認識する必要があります。これを行うには 2 つの方法があります。

  • クッキー。よりクリーンでより一般的な方法ですが、1 人のユーザーによるすべてのブラウザー タブとウィンドウがセッションを共有することを意味します。IMO これは実際には望ましいことです。タブを非常に集中的に使用する
  • URL書き換え。サイト上のすべての URL には、セッション ID が追加されています。これは手間がかかります (サイト内リンクがある場所ならどこでも何かをしなければなりません) が、異なるタブで個別のセッションを持つことができますが、リンクから開いたタブは引き続きセッションを共有します。また、ユーザーがサイトにアクセスするときは常にログインする必要があることも意味します。

とにかく何をしようとしていますか?タブに個別のセッションを持たせたいのはなぜですか? セッションをまったく使用せずに目標を達成する方法があるのではないでしょうか?

編集: テスト用に、他のソリューションを見つけることができます (別の VM で複数のブラウザー インスタンスを実行するなど)。1 人のユーザーが同時に異なる役割で行動する必要がある場合、1 回のログインで複数の役割を持つことができるように、「役割」の概念をアプリで処理する必要があります。Cookie ベースのセッションでブラウザのタブを個別に処理することは単純に不可能であるため、URL の書き換えを使用するか、単に現在の状況を受け入れるかを決定する必要があります。

于 2008-12-15T15:40:57.590 に答える
16

window.name Javascriptプロパティは、タブアクティビティ全体で存続する唯一のものですが、(URLガフの代わりに)独立したままにすることができます。

于 2011-06-20T20:51:30.573 に答える
15

すべきではありません。そのようなことをしたい場合は、オンザフライで URL を記述してアプリケーションの単一インスタンスを使用するようにユーザーに強制する必要があります。

なぜそれが必要なのかはわかりませんが、完全に使用できないアプリケーションを作成する必要がない限り、そうしないでください。

于 2008-12-15T15:35:51.983 に答える
13

私は新しいソリューションを思いつきました。これにはオーバーヘッドが少しありますが、これまでのところプロトタイプとして機能しているようです。タブを切り替えるたびにパスワードを再要求することでこれを適応させることができますが、ログインするための名誉あるシステム環境にいることが1つの前提です.

localStorage (または同等のもの) と HTML5 ストレージ イベントを使用して、新しいブラウザー タブでアクティブなユーザーが切り替わったことを検出します。その場合は、現在のウィンドウを使用できないというメッセージを含むゴースト オーバーレイを作成します (または、一時的にウィンドウを無効にします。これほど目立たないようにしたい場合があります)。ウィンドウがフォーカスを取り戻したら、AJAX 要求ログを送信します。ユーザーが戻ってきます。

このアプローチの 1 つの注意点: 通常の AJAX 呼び出し (つまり、セッションに依存する呼び出し) を、フォーカスのないウィンドウで発生させることはできません (たとえば、呼び出しが遅延後に発生した場合)。その前に手動で AJAX 再ログイン呼び出しを行います。つまり、最初に AJAX 関数をチェックして localStorage.currently_logged_in_user_id === window.yourAppNameSpace.user_id を確認し、そうでない場合は AJAX 経由で最初にログインするだけです。

もう 1 つは競合状態です。ウィンドウを混乱させるほど速く切り替えられると、relogin1->relogin2->ajax1->ajax2 のシーケンスになり、ajax1 が間違ったセッションで作成される可能性があります。これを回避するには、ログイン AJAX リクエストを配列にプッシュしてからストレージにプッシュし、新しいログイン リクエストを発行する前に、現在のすべてのリクエストを中止します。

最後に注意すべき点は、ウィンドウの更新です。AJAX ログイン要求がアクティブであるが完了していないときに誰かがウィンドウを更新すると、間違った人の名前で更新されます。この場合、非標準の beforeunload イベントを使用して、混同の可能性についてユーザーに警告し、[キャンセル] をクリックするように依頼し、その間に AJAX ログイン要求を再発行できます。次に、リクエストが完了する前に [OK] をクリックする (または、このケースでは残念ながら [OK] がデフォルトであるため、誤って Enter キーまたはスペースバーを押してしまう) ことによってのみ失敗する可能性があります。 F5 および Ctrl+R/Alt+R の押下を検出します。これはほとんどの場合機能しますが、ユーザーのキーボード ショートカットの再構成または別の OS の使用によって妨げられる可能性があります。ただし、これは実際には少し特殊なケースであり、最悪のシナリオは決して悪いものではありません: 名誉あるシステム構成では、間違った人としてログインすることになります (しかし、ページを色、スタイル、目立つように表示される名前、等。); パスワード構成では、パスワードを最後に入力した人がログアウトまたはセッションを共有した責任があります。または、この人が実際に現在のユーザーである場合、違反はありません。

しかし、最終的には、プロファイルを設定したり、IE を使用したり、URL を書き換えたりする必要なく、(うまくいけば) 本来の動作をする、タブごとに 1 ユーザーのアプリケーションができあがります。ただし、その特定のタブにログインしている各タブで、誰がログインしているかを明確にしてください...

于 2009-07-15T20:53:51.033 に答える
10

私たちはこの問題を抱えていましたが、非常に簡単に解決しました。プログラミングが含まれていないため、簡単です。私たちがやりたかったのは、ユーザーがセッションを競合させることなく、同じブラウザー ウィンドウ内で複数のアカウントにログインできるようにすることでした。

したがって、解決策はランダムなサブドメインでした。

23423.abc.com
242234.abc.com
235643.abc.com

そのため、システム管理者に、abc.com ではなく *.abc.com の SSL 証明書を構成するように依頼しました。次に、コードを少し変更するだけで、ユーザーがログインを試みるたびに、ランダムなサブドメイン番号でタブにログインします。そのため、各タブは個別に独自のセッションを持つことができます。また、競合を避けるために、ユーザー ID のハッシュまたは md5 を使用して乱数を開発しました。

于 2014-04-15T06:17:13.597 に答える
2

おそらく必要なのは、タブ間でナビゲーション状態を維持することであり、タブごとに1つのセッションを具体的に作成することではないと思います。これはまさに、Seamフレームワークが会話スコープ/コンテキストで達成することです。それらの実装は、会話IDが各要求で伝播され、サーバー側で会話の概念を作成するという事実に依存しています。これは、セッションと要求の間にあるものです。ナビゲーションフロー制御と状態管理が可能です。

これは主にJSFを対象としていますが、http: //docs.jboss.org/seam/latest/reference/en-US/html_single/#d0e3620からアイデアを得ることができるものかどうかを確認してください。

于 2012-08-02T18:51:46.437 に答える
2

リンク書き換えを使用して、単一のページ (例: index.html/jsp/whatever) から開始するときに、すべての URL に一意の識別子を追加できます。ブラウザーはすべてのタブで同じ Cookie を使用するため、Cookie に入力したすべての情報が一意になるわけではありません。

于 2008-12-15T15:15:13.117 に答える
2

JavaScript で、同じ Cookie ベースの sessionId の下にある別のブラウザ ウィンドウから一意に識別するにはどうすればよいですか?

基本的に window.name を使用します。設定されていない場合は、一意の値に設定して使用します。同じセッションに属するタブ間で異なります。

于 2012-10-05T07:09:25.903 に答える
2

注: ここでの解決策は、アプリケーションの設計段階で行う必要があります。後でこれを設計するのは難しいでしょう。

非表示フィールドを使用して、セッション識別子を渡します

これが機能するには、各ページにフォームが含まれている必要があります。

<form method="post" action="/handler">

  <input type="hidden" name="sessionId" value="123456890123456890ABCDEF01" />
  <input type="hidden" name="action" value="" />

</form>

ナビゲーションを含むあなたの側のすべてのアクションは、フォームを POST バックします (必要に応じて を設定actionします)。「安全でない」リクエストの場合、送信するデータの JSON 値を含むなど、別のパラメーターを含めることができます。

<input type="hidden" name="action" value="completeCheckout" />
<input type="hidden" name="data" value='{ "cardNumber" : "4111111111111111", ... ' />

Cookie がないため、各タブは独立しており、同じブラウザー内の他のセッションを認識しません。

特にセキュリティに関しては、多くの利点があります。

  • JavaScript や HTML5 に依存しません。
  • 本質的にCSRFから保護します。
  • Cookie に依存しないため、POODLEから保護します。
  • セッション固定に対して脆弱ではありません。
  • 戻るボタンの使用を防ぐことができます。これは、ユーザーがサイト内で設定されたパスをたどることが望ましい場合に望ましいことです (つまり、順不同のリクエストによって攻撃される可能性があるロジック バグを防ぐことができます)。

いくつかの欠点:

  • 戻るボタンの機能が必要な場合があります。
  • すべてのアクションが POST であるため、キャッシングではあまり効果的ではありません。

詳細はこちら

于 2015-06-08T14:31:24.990 に答える
1

Spring Session は同じブラウザーで複数のセッションをサポートします サンプルと実装の詳細を見てください http://docs.spring.io/spring-session/docs/current/reference/html5/guides/users.html

于 2015-02-20T07:45:54.753 に答える
1

別の有効な方法は、一意のウィンドウ ID を作成し、この値をセッション ID と共にデータベース テーブルに格納することです。私がよく使用するウィンドウ ID は整数 (現在) です。この値は、ウィンドウが開かれたときに作成され、ウィンドウがリフレッシュ、再ロード、またはそれ自体に送信された場合に、同じウィンドウに再割り当てされます。ウィンドウ値 (入力) は、リンクを使用してローカル テーブルに保存されます。値が必要な場合は、ウィンドウ ID / セッション ID リンクに基づいてデータベース テーブルから取得されます。このアプローチにはローカル データベースが必要ですが、事実上、誰にでもできる方法です。データベース テーブルの使用は簡単でしたが、ローカル配列がうまく機能しない理由はわかりません。

于 2009-09-21T17:09:46.713 に答える
0

セッション ID Cookie を操作するためにクライアント側に変更を加えた多くの実装を目にします。しかし、一般的にセッション ID Cookie は HttpOnly である必要があるため、Java スクリプトはアクセスできません。そうしないと、XSS によるセッション ハイジャックが発生する可能性があります。

于 2015-03-16T05:23:34.587 に答える
0

timeStamp がまだ設定されていない場合は、window.sessionStorage に保存します。これにより、各タブに一意の値が与えられます(URLが同じであっても)

http://www.javascriptkit.com/javatutors/domstorage.shtml

https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage

お役に立てれば。

于 2013-10-05T20:54:04.613 に答える
0

私も同じことをしたいと思ったので、この記事を読んでいます。私が取り組んでいるアプリケーションについても同様の状況があります。そして実際には、実用性よりもテストの問題です。

これらの回答、特に Michael Borgwardt による回答を読んだ後、存在する必要があるワークフローに気付きました。

  1. ユーザーがログイン画面に移動した場合は、既存のセッションを確認します。存在する場合は、ログイン画面をバイパスしてウェルカム画面に送信します。
  2. ユーザー (私の場合) が登録画面に移動した場合は、既存のセッションを確認します。存在する場合は、そのセッションをログアウトすることをユーザーに知らせます。同意する場合は、ログアウトして登録を開始します。

これにより、ユーザーがセッションで「別のユーザー」のデータを見るという問題が解決されます。彼らは自分のセッションで「別のユーザーの」データを実際に見ているのではなく、開いている唯一のセッションからのデータを実際に見ています。一部の操作では一部のセッション データが上書きされ、他の操作では上書きされないため、明らかにこれにより興味深いデータが生成されるため、その 1 つのセッションでデータの組み合わせが得られます。

さて、テストの問題に対処します。唯一の実行可能なアプローチは、プリプロセッサ ディレクティブを活用して、Cookie を使用しないセッションを使用する必要があるかどうかを判断することです。ほら、特定の環境用の特定の構成を構築することで、環境とその使用目的についていくつかの仮定を立てることができます。これにより、技術的には 2 人のユーザーを同時にログインさせることができ、テスターはそれらのサーバー セッションからログアウトすることなく、同じブラウザー セッションから複数のシナリオをテストできます。

ただし、このアプローチにはいくつかの重大な注意点があります。特に、テスターがテストしているものは本番環境で実行されるものではないという事実です。

ですから、これは最終的に悪い考えだと言わざるを得ないと思います。

于 2013-07-18T17:40:46.493 に答える
0

アプリケーションで各タブが異なるフローを実行し、両方のフローを混在させると問題が発生することが原因である場合は、セッション オブジェクトを「地域化」して、各フローがセッションの異なるリージョンを使用するようにすることをお勧めします。

このリージョンは、フローごとに異なるプレフィックスを持つように単純に実装できます。または、セッション オブジェクトが複数のマップ (フローごとに 1 つ) を保持し、セッション属性の代わりにこれらのマップを使用します。代わりに使用してください。

于 2016-04-19T08:04:59.273 に答える
0
How to differ sessions in browser-tabs?

ブラウザーのタブでセッションを区別する最も簡単な方法は、特定のドメインで Cookie の設定を禁止することです。そうすれば、別々のタブから別々のセッションを持つことができます。このドメイン (www.xyz.com) からの Cookie を許可しないとします。タブ 1 を開き、ログインしてブラウジングを開始します。次にタブ 2 を開くと、同じユーザーまたは別のユーザーとしてログインできます。どちらの方法でも、タブ 1 とは別のセッションになります。

もちろん、これはクライアント側を制御できる場合に可能です。それ以外の場合は、ここの人々によって規定された解決策が適用されます。

于 2013-11-22T08:47:32.553 に答える
0

あなたがする必要があります

1- アカウント リストの Cookie を保存する

2-オプションで、デフォルトの Cookie を保存します

3- acc1、acc2 などのインデックスを持つ各アカウントのストア

4- アカウントのインデックスを表す URL を入力します。そうでない場合は、Google メール domain.com/0/some-url のようなデフォルトの URL を選択します >> 0 はアカウントのインデックスを表します。 urlwrite を使用する

5- Cookie を選択するときは、アカウントのインデックスを表す URL パスに従って選択します

よろしく

于 2014-10-25T01:02:24.430 に答える