web-dev-qa-db-ja.com

ブラウザタブのセッションをどのように変えるのですか?

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を使用)、正しいコマンドを使用してブラウザー(FF、IE7またはOpera)を開きますURL(localhost/context1/testpage.jsp)、入力に名前を入力し、フォームを送信します。次に、同じブラウザで新しいタブを開くと、新しいタブに自分の名前(セッションから取得)が表示されます。ブラウザキャッシュに注意してください、時々それが起こらないように見えますが、それはキャッシュ内にあり、2番目のタブを更新してください。

ありがとう。

130
Oriol Terradas

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

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

89

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

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

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

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

22

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

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

17
dr. evil

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

16
Dave Bish

私は新しいソリューションを思いつきました。これにはわずかなオーバーヘッドがありますが、これまでのところプロトタイプとして機能しているようです。 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リクエストを配列にプッシュし、onstorageで新しいログインリクエストを発行する前に、現在のリクエストをすべて中止します。

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

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

13
Kev

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

そのため、解決策はランダムなサブドメインでした。

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

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

10
user3534653

ここで正直に言います。 。 .すべて上記は真実である場合とそうでない場合がありますが、それはすべて方法複雑すぎる、またはサーバー側で使用されているタブがわからないということです。

時々、オッカムのカミソリを塗る必要があります。

これがオッカムのアプローチです:(いいえ、私はオッカムではありません、彼は1347年に亡くなりました)

1)ロード時に、ブラウザに一意のIDをページに割り当てます。 。 。ウィンドウにまだIDがない場合にのみ(したがって、プレフィックスと検出を使用します)

2)持っているすべてのページ(グローバルファイルなどを使用)で、コードを配置してフォーカスイベントやマウスオーバーイベントを検出します。 (コードの記述を簡単にするために、この部分にjqueryを使用します)

3)フォーカス(および/またはマウスオーバー)機能で、window.nameを含むCookieを設定します

4)タブ固有のデータの読み取り/書き込みが必要な場合、サーバー側からそのCookie値を読み取ります。

クライアント側:

//Events 
$(window).ready(function() {generateWindowID()});
$(window).focus(function() {setAppId()});
$(window).mouseover(function() {setAppId()});


function generateWindowID()
{
    //first see if the name is already set, if not, set it.
    if (se_appframe().name.indexOf("SEAppId") == -1){
            "window.name = 'SEAppId' + (new Date()).getTime()
    }
    setAppId()
}

function setAppId()
{
    //generate the cookie
    strCookie = 'seAppId=' + se_appframe().name + ';';
    strCookie += ' path=/';

    if (window.location.protocol.toLowerCase() == 'https:'){
        strCookie += ' secure;';
    }

    document.cookie = strCookie;
}

サーバー側(C#-例として)

//variable name 
string varname = "";
HttpCookie aCookie = Request.Cookies["seAppId"];
if(aCookie != null) {
     varname  = Request.Cookies["seAppId"].Value + "_";
}
varname += "_mySessionVariable";

//write session data 
Session[varname] = "ABC123";

//readsession data 
String myVariable = Session[varname];

できた.

4
Mike A.

javascriptでは、同じcookiedbased sessionIdの下にある別のブラウザウィンドウから一意に識別する方法

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

2
akkishore

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

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

2
lsoliveira

動作するもう1つのアプローチは、一意のウィンドウIDを作成し、この値をセッションIDとともにデータベーステーブルに格納することです。私がよく使用するウィンドウIDはinteger(now)です。この値は、ウィンドウが更新、再ロード、またはウィンドウに送信された場合、ウィンドウが開かれ、同じウィンドウに再割り当てされたときに作成されます。ウィンドウの値(入力)は、リンクを使用してローカルテーブルに保存されます。値が必要な場合、ウィンドウID /セッションIDリンクに基づいてデータベーステーブルから取得されます。このアプローチにはローカルデータベースが必要ですが、事実上、確実です。データベーステーブルの使用は私にとって簡単でしたが、ローカル配列が同様に機能しない理由はわかりません。

1
Stephen

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

1
Bombe

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

1
vasa.v03

最近、Cookieを使用してこの問題の解決策を開発しました。ここに私のソリューションへのリンクがあります。 ASP.NETを使用したソリューションのサンプルコードも含まれています。必要に応じて、これをJSPまたはServeletsに適合させることができます。

https://sites.google.com/site/sarittechworld/track-client-windows

1
Sarit Kommineni

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

0
vasa.v03

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

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

0
hussein.g

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

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

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

お役に立てれば。

0
guest

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

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

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

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

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

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

よろしく

0
Mhmd

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

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

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

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

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

</form>

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

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

Cookieが存在しないため、各タブは独立しており、同じブラウザ内の他のセッションの情報を持ちません。

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

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

いくつかの欠点:

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

詳細はこちら

0
SilverlightFox

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

これらの答え、特にマイケル・ボルグワードによって与えられた答えを読んだ後、私は存在する必要のあるワークフローに気付きました。

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

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

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

ただし、このアプローチにはいくつかの重大な警告があります。テスターがテストしているのは、実稼働環境で実行されるnotであるという事実です。

だから私は言わなければならないと思う、これは最終的には悪い考えだ。

0
Mike Perrenoud

私はこれを次の方法で解決しました:

  • ウィンドウに名前を割り当てました。この名前は接続リソースと同じです。
  • プラス1は、接続を接続するためにCookieに保存されているものを削除します。
  • すべてのxmloutput応答をキャプチャし、sidとridをjson形式でcookieに割り当てる関数を作成しました。 window.nameごとにこれを行います。

ここにコード:

var deferred = $q.defer(),
        self = this,
        onConnect = function(status){
          if (status === Strophe.Status.CONNECTING) {
            deferred.notify({status: 'connecting'});
          } else if (status === Strophe.Status.CONNFAIL) {
            self.connected = false;
            deferred.notify({status: 'fail'});
          } else if (status === Strophe.Status.DISCONNECTING) {
            deferred.notify({status: 'disconnecting'});
          } else if (status === Strophe.Status.DISCONNECTED) {
            self.connected = false;
            deferred.notify({status: 'disconnected'});
          } else if (status === Strophe.Status.CONNECTED) {
            self.connection.send($pres().tree());
            self.connected = true;
            deferred.resolve({status: 'connected'});
          } else if (status === Strophe.Status.ATTACHED) {
            deferred.resolve({status: 'attached'});
            self.connected = true;
          }
        },
        output = function(data){
          if (self.connected){
            var rid = $(data).attr('rid'),
                sid = $(data).attr('sid'),
                storage = {};

            if (localStorageService.cookie.get('day_bind')){
              storage = localStorageService.cookie.get('day_bind');
            }else{
              storage = {};
            }
            storage[$window.name] = sid + '-' + rid;
            localStorageService.cookie.set('day_bind', angular.toJson(storage));
          }
        };
    if ($window.name){
      var storage = localStorageService.cookie.get('day_bind'),
          value = storage[$window.name].split('-')
          sid = value[0],
          rid = value[1];
      self.connection = new Strophe.Connection(BoshService);
      self.connection.xmlOutput = output;
      self.connection.attach('bosh@' + BoshDomain + '/' + $window.name, sid, parseInt(rid, 10) + 1, onConnect);
    }else{
      $window.name = 'web_' + (new Date()).getTime();
      self.connection = new Strophe.Connection(BoshService);
      self.connection.xmlOutput = output;
      self.connection.connect('bosh@' + BoshDomain + '/' + $window.name, '123456', onConnect);
    }

お役に立てば幸いです

0
German Sanchez
How to differ sessions in browser-tabs?

ブラウザのタブでセッションを変更する最も簡単な方法は、特定のドメインでCookieを設定できないようにすることです。これにより、個別のタブから個別のセッションを作成できます。このドメインwww.xyz.comからのCookieを禁止するとします。タブ1を開き、ログインしてブラウジングを開始します。次に、タブ2を開き、同じユーザーまたは別のユーザーとしてログインできます。いずれにしても、タブ1とは別のセッションがあります。以降も同様です。

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

0
Kingz