Wie unterscheidet man Sitzungen in Browser-Tabs?

In einer Web-Anwendung, die in Java mit JSP und Servlets implementiert ist; Wenn ich Informationen in der Benutzersitzung speicher, werden diese Informationen von allen Registerkarten desselben Browsers gemeinsam genutzt. Wie unterscheiden sich Sitzungen in den Browser-Tabs? In diesem Beispiel:

    
User:

Kopieren Sie diesen Code in eine JSP-Seite ( testpage.jsp ), stellen Sie diese Datei in einem vorhandenen Kontext einer Webanwendung auf dem Server testpage.jsp (ich verwende Apache Tomcat) und öffnen Sie dann einen Browser (FF, IE7 oder Opera) mit der korrekten URL ( localhost/context1/testpage.jsp ), geben Sie Ihren Namen in die Eingabe ein und senden Sie das Formular ab. Öffnen Sie dann im selben Browser eine neue Registerkarte, und auf der neuen Registerkarte sehen Sie dann Ihren Namen (aus der Sitzung abgerufen). Seien Sie vorsichtig mit dem Browser-Cache, manchmal scheint es, dass es nicht passiert, aber es ist im Cache, aktualisieren Sie die zweite Registerkarte.

Vielen Dank.

Sie können HTML5 SessionStorage (window.sessionStorage) verwenden. Sie werden eine zufällige ID generieren und in der Session Storage per Browser Tab speichern. Dann hat jeder Browser Tab seine eigene ID.

Daten, die mit sessionStorage gespeichert werden, bleiben nicht in den Browser-Tabs erhalten, auch wenn zwei Tabs Webseiten aus demselben Domain-Ursprung enthalten. Mit anderen Worten, Daten innerhalb von sessionStorage beschränken sich nicht nur auf die Domäne und das Verzeichnis der aufrufenden Seite, sondern auch auf die Browserregisterkarte, in der die Seite enthalten ist. Vergleichen Sie dies mit Sitzungscookies, die Daten von Registerkarte zu Registerkarte beibehalten.

Sie müssen feststellen, dass serverseitige Sitzungen ein künstliches Add-On zu HTTP sind. Da HTTP zustandslos ist, muss der Server irgendwie erkennen, dass eine Anfrage zu einem bestimmten Benutzer gehört, den er kennt und für den er eine Sitzung hat. Es gibt 2 Möglichkeiten, dies zu tun:

  • cookies. Die sauberere und populärere Methode, aber es bedeutet, dass alle Browser Tabs und Fenster von einem Benutzer die Sitzung teilen – IMO das ist in der Tat wünschenswert, und ich wäre sehr verärgert über eine Website, die mich für jeden neuen Tab anmelden, seit ich Verwenden Sie Tabs sehr intensiv
  • URL-Umschreibung Für jede URL auf der Site wird eine Sitzungs-ID angehängt. Das ist mehr Arbeit (Sie müssen etwas unternehmen, wo immer Sie eine site-interne Verbindung haben), aber es ermöglicht separate Sitzungen in verschiedenen Tabs, obwohl Tabs, die über den Link geöffnet werden, die Sitzung weiterhin teilen. Es bedeutet auch, dass sich der Benutzer immer anmelden muss, wenn er auf Ihre Website kommt.

Was versuchst du überhaupt zu tun? Warum sollten Tabs getrennte Sitzungen haben? Vielleicht gibt es einen Weg, um Ihr Ziel zu erreichen, ohne Sitzungen überhaupt zu verwenden?

Bearbeiten: Zum Testen können andere Lösungen gefunden werden (z. B. Ausführen mehrerer Browserinstanzen auf separaten VMs). Wenn ein Benutzer gleichzeitig in verschiedenen Rollen agieren muss, sollte das “Rollen” -Konzept in der App behandelt werden, damit eine Anmeldung mehrere Rollen haben kann. Sie müssen entscheiden, ob dies, das Umschreiben von URLs oder das Leben mit der aktuellen Situation, akzeptabler ist, da es einfach nicht möglich ist, Browser-Tabs mit cookiebasierten Sitzungen separat zu behandeln.

Die JavaScript-Eigenschaft window.name ist die einzige Eigenschaft, die über die Tab-Aktivität hinaus bestehen bleibt, aber unabhängig von der URL-Adresse bleiben kann.

Du solltest nicht. Wenn Sie so etwas tun möchten, müssen Sie den Benutzer zwingen, eine einzelne Instanz Ihrer Anwendung zu verwenden, indem Sie URLs im laufenden Betrieb schreiben und eine SessionID-ID (nicht SessionID wird nicht funktionieren) verwenden und diese in jeder URL übergeben.

Ich weiß nicht, warum Sie es brauchen, aber wenn Sie keine völlig unbrauchbare Anwendung brauchen, tun Sie es nicht.

Ich habe mir eine neue Lösung ausgedacht, die ein wenig Overhead hat, aber anscheinend so weit funktioniert wie ein Prototyp. Eine Voraussetzung ist, dass Sie sich in einer Systemumgebung für die Anmeldung befinden, obwohl dies angepasst werden könnte, indem Sie jedes Mal, wenn Sie Tabs wechseln, ein Passwort erneut anfordern.

Verwenden Sie localStorage (oder ein gleichwertiges Format) und das HTML5-Speicherereignis, um zu erkennen, wann eine neue Browserregisterkarte den aktiven Benutzer gewechselt hat. Erstellen Sie in diesem Fall ein Geister-Overlay mit der Meldung, dass Sie das aktuelle Fenster nicht verwenden können (oder das Fenster vorübergehend deaktivieren). Wenn das Fenster wieder scharf wird, senden Sie eine AJAX-Anforderungsprotokollierung der Benutzer zurück.

Eine Einschränkung dieses Ansatzes: Sie können keine normalen AJAX-Anrufe (dh solche, die von Ihrer Sitzung abhängen) in einem Fenster ausführen, das nicht den Fokus hat (z. B. wenn Sie nach einer Verzögerung einen Anruf hatten), es sei denn Sie müssen zuvor manuell einen AJAX-Neuanruf tätigen. Alles, was Sie wirklich tun müssen, ist Ihre AJAX-functionsprüfung, um sicherzustellen, dass localStorage.currently_logged_in_user_id === window.yourAppNameSpace.user_id, und wenn nicht, melden Sie sich zuerst über AJAX an.

Eine andere ist die Race Conditions: Wenn Sie Windows schnell genug wechseln können, um es zu verwirren, können Sie mit einer relogin1-> relogin2-> ajax1-> ajax2-Sequenz enden, wobei ajax1 in der falschen Sitzung erstellt wird. Umgehen Sie das, indem Sie Anmelde-AJAX-Anfragen auf ein Array ablegen, und dann auf Speichern, und bevor Sie eine neue Anmeldeanforderung absetzen, brechen Sie alle aktuellen Anfragen ab.

Der letzte Fehler, auf den Sie achten sollten, sind Fensteraktualisierungen. Wenn jemand das Fenster aktualisiert, während eine AJAX-Anmeldeanforderung aktiv, aber nicht abgeschlossen ist, wird sie im Namen der falschen Person aktualisiert. In diesem Fall können Sie das Ereignis non-standard beforeunload verwenden, um den Benutzer vor der möglichen Verwechslung zu warnen, und ihn auf Abbrechen klicken, während eine AJAX-Anmeldeanforderung erneut ausgegeben wird. Dann können sie es nur verpfuschen, indem Sie auf OK klicken, bevor die Anfrage abgeschlossen ist (oder versehentlich die Eingabetaste / Leertaste drücken, weil OK – leider für diesen Fall – der Standardwert ist.) Es gibt andere Möglichkeiten, diesen Fall zu behandeln Wenn Sie F5 und Ctrl + R / Alt + R drücken, wird dies in den meisten Fällen funktionieren, könnte aber durch eine Neukonfiguration der Tastenkombination oder eine alternative Verwendung des Betriebssystems vereitelt werden. Dies ist jedoch in der Realität ein echter Grenzfall, und die Worst – Case – Szenarien sind nie so schlimm: In einer Ehren – Systemkonfiguration würden Sie als falsche Person angemeldet sein (aber Sie können deutlich machen, dass dies der Fall ist) Fall durch Personalisierung der Seiten mit colors, Stilen, prominent angezeigten Namen, etc.); In einer Passwort-Konfiguration ist die letzte Person, die ihr Passwort eingegeben hat, um sich abgemeldet oder ihre Sitzung geteilt zu haben, oder wenn diese Person tatsächlich der aktuelle Benutzer ist, dann gibt es keine Verletzung.

Aber am Ende gibt es eine Anwendung für einen Benutzer pro Tab, die (hoffentlich) nur so funktioniert, wie sie sollte, ohne dass Sie unbedingt Profile einrichten, IE verwenden oder URLs neu schreiben müssen. Stellen Sie jedoch sicher, dass Sie in jedem Register, das auf diesem bestimmten Tab angemeldet ist, auffallen.

Wir hatten dieses Problem und wir haben es sehr einfach getriggers. Ich meine, einfach, weil keine Programmierung beteiligt ist. Was wir tun wollten, war, dass sich ein Benutzer in demselben Browserfenster bei mehreren Konten anmelden konnte, ohne die Sitzungen zu beeinträchtigen.

Die Lösung bestand aus zufälligen Subdomänen.

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

Also haben wir unseren Systemadministrator gebeten, die SSL-Zertifikate für * .abc.com eher abc.com zu konfigurieren. Dann wird mit wenig Codewechsel jedes Mal, wenn ein Benutzer sich anmeldet, ein Tab mit einer zufälligen Subdomain-Nummer eingeloggt. So könnte jeder Tab unabhängig eine eigene Sitzung haben. Um Konflikte zu vermeiden, entwickelten wir die Zufallszahl mit einem Hash oder md5 der Benutzer-ID.

Ich werde hier ehrlich sein. . . alles oben kann oder kann nicht wahr sein, aber es scheint alles zu kompliziert, oder nicht zu wissen, welche Registerkarte serverseitig verwendet wird.

Manchmal müssen wir Ockhams razor anwenden.

Hier ist der Ansatz von Occam: (Nein, ich bin nicht Ockham, er starb 1347)

1) Weisen Sie Ihrer Seite beim Laden eine eindeutige ID zu. . . genau dann, wenn das Fenster noch keine ID hat (also Präfix und Erkennung verwenden)

2) auf jeder Seite, die Sie haben (verwenden Sie eine globale Datei oder etwas), setzen Sie einfach Code ein, um das Fokusereignis und / oder mouseover Ereignis zu ermitteln. (Ich werde jQuery für diesen Teil verwenden, um das Schreiben von Code zu vereinfachen)

3) Setze in deiner Fokus (und / oder Mouseover) -function ein Cookie mit dem window.name darin

4) Lesen Sie diesen Cookie-Wert von Ihrer Server-Seite, wenn Sie Tab-spezifische Daten lesen / schreiben müssen.

Kundenseite:

 //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; } 

Serverseite (C # – zum Beispiel)

 //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]; 

Erledigt.

Ich denke, was Sie wahrscheinlich wollen, ist, den Navigationszustand über Registerkarten zu behalten und nicht spezifisch eine einzelne Sitzung pro Vorsprung zu verursachen. Dies ist genau das, was das Seam-Framework mit seinem Konversationsumfang / -kontext erreicht. Ihre Implementierung beruht auf der Tatsache, dass eine Konversations-ID mit jeder Anfrage verbreitet wird und die Vorstellung einer Konversation auf der Serverseite erzeugt, was zwischen einer Sitzung und einer Anfrage liegt. Es ermöglicht die Steuerung des Navigationsflusses und die Statusverwaltung.

Obwohl dies hauptsächlich auf JSF abzielt, sehen Sie nach und prüfen Sie, ob Sie dazu einige Ideen haben können: http://docs.jboss.org/seam/latest/reference/en-US/html_single/#d0e3620

Wie kann ich in javascript ein Browserfenster eindeutig von einem anderen identifizieren, das sich unter derselben cookiedbased sessionId befindet?

Verwenden Sie im Wesentlichen window.name. Wenn es nicht festgelegt ist, legen Sie es auf einen eindeutigen Wert fest und verwenden Sie es. Dies gilt für alle Registerkarten, die zu derselben Sitzung gehören.

Sie können das Link-Rewriting verwenden, um einen eindeutigen Bezeichner an alle URLs anzuhängen, wenn Sie auf einer einzelnen Seite beginnen (z. B. index.html / jsp / was auch immer). Der Browser verwendet die gleichen Cookies für alle Ihre Tabs, so dass alles, was Sie in Cookies eingeben, nicht eindeutig ist.

Ich habe kürzlich eine Lösung für dieses Problem mit Cookies entwickelt. Hier ist ein Link zu meiner Lösung. Ich habe auch Beispielcode der Lösung mit ASP.NET enthalten, sollten Sie in der Lage sein, dies an JSP oder Servelets anzupassen, wenn Sie benötigen.

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

Spring Session unterstützt mehrere Sitzungen im selben Browser. Sehen Sie sich die Beispiel- und Implementierungsdetails http://docs.spring.io/spring-session/docs/current/reference/html5/guides/users.html an

Ein anderer Ansatz, der funktioniert, besteht darin, eine eindeutige Fenster-ID zu erstellen und diesen Wert zusammen mit der Sitzungs-ID in einer databasetabelle zu speichern. Die Fenster-ID, die ich häufig verwende, ist eine Ganzzahl (jetzt). Dieser Wert wird erstellt, wenn ein Fenster geöffnet und demselben Fenster erneut zugewiesen wird, wenn das Fenster aktualisiert, neu geladen oder an sich selbst gesendet wird. Fensterwerte (Eingaben) werden in der lokalen Tabelle über den Link gespeichert. Wenn ein Wert erforderlich ist, wird er aus der databasetabelle basierend auf der Fenster-ID / Sitzungs-ID-Verknüpfung abgerufen. Während dieser Ansatz eine lokale database benötigt, ist er praktisch narrensicher. Die Verwendung einer databasetabelle war für mich einfach, aber ich sehe keinen Grund, warum lokale Arrays nicht genauso gut funktionieren würden.

Ich habe diesen Beitrag gelesen, weil ich dachte, ich wollte das Gleiche machen. Ich habe eine ähnliche Situation für eine Anwendung, an der ich arbeite. Und es geht wirklich darum, mehr zu testen als praktisch.

Nachdem ich diese Antworten, insbesondere die von Michael Borgwardt, gelesen habe, habe ich den notwendigen Workflow erkannt:

  1. Wenn der Benutzer zum Anmeldebildschirm navigiert, suchen Sie nach einer vorhandenen Sitzung. Wenn einer vorhanden ist, umgehen Sie den Anmeldebildschirm und senden Sie ihn an den Begrüßungsbildschirm.
  2. Wenn der Benutzer (in meinem Fall) zum Registrierungsbildschirm navigiert, prüfen Sie, ob eine Sitzung vorhanden ist. Wenn einer vorhanden ist, informieren Sie den Benutzer, dass Sie diese Sitzung protokollieren werden. Wenn Sie einverstanden sind, melden Sie sich ab und beginnen Sie mit der Registrierung.

Dies wird das Problem lösen, dass der Benutzer die Daten eines anderen Benutzers in seiner Sitzung sieht. Sie sehen nicht wirklich die Daten eines anderen Benutzers in ihrer Sitzung, sie sehen wirklich die Daten von der einzigen Sitzung, die sie geöffnet haben. Offensichtlich verursacht dies einige interessante Daten, da einige Operationen einige Sitzungsdaten überschreiben und keine anderen, sodass Sie eine Kombination von Daten in dieser einzelnen Sitzung haben.

Jetzt, um das Testproblem anzugehen. Der einzige gangbare Ansatz wäre es, Präprozessor-Direktiven zu nutzen, um festzustellen, ob Sitzungen ohne Cookies verwendet werden sollten. Sehen Sie, indem ich eine spezifische Konfiguration für eine bestimmte Umgebung erstelle, kann ich einige Annahmen über die Umgebung treffen und wofür sie verwendet wird. Dies würde es mir ermöglichen, technisch gesehen zwei Benutzer gleichzeitig angemeldet zu haben, und der Tester könnte mehrere Szenarien aus derselben Browsersitzung testen, ohne sich jemals von diesen Serversitzungen abzumelden.

Dieser Ansatz hat jedoch einige ernsthafte Vorbehalte. Nicht zuletzt ist das, was der Tester testet, nicht das, was in der Produktion läuft.

Ich denke, ich muss sagen, das ist letztlich eine schlechte Idee.

Speichern Sie den timeStamp in window.sessionStorage, wenn er nicht bereits festgelegt ist. Dies gibt einen eindeutigen Wert für jeden Tab (auch wenn die URLs gleich sind)

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

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

Hoffe das hilft.

 How to differ sessions in browser-tabs? 

Die einfachste Möglichkeit, Sitzungen in Browser-Tabs zu unterscheiden, besteht darin, dass Ihre bestimmte Domain keine Cookies setzen darf. Auf diese Weise können Sie getrennte Sitzungen von separaten Tabs haben. Angenommen, Sie verweigern Cookies von dieser Domain: http://www.xyz.com. Sie öffnen Tab 1, melden sich an und beginnen mit dem Browsen. Dann öffnen Sie Tab 2, und Sie können sich entweder als derselbe Benutzer oder als ein anderer anmelden; So oder so, Sie werden eine Sitzung getrennt von Tab 1 haben. Und so weiter.

Aber natürlich ist dies möglich, wenn Sie die Kontrolle über die Client-Seite haben. Ansonsten sollten die von den Leuten hier vorgeschriebenen Lösungen gelten.

Du wirst es tun müssen

1- Speichern Sie ein Cookie für die Kontenliste

2- Optional speichern Sie einen Cookie für den Standard

3-store für jedes Konto mit seinem Index wie acc1, acc2

4- in die URL stellen etwas den Index der Konten und wenn nicht, Sie werden die Standard-wie Google Mail domain.com / 0 / some -url >> 0 hier den Index des Kontos auch Sie möglicherweise müssen, wie zu wählen benutze urlwrite

5- Wenn Sie einen Cookie auswählen, wählen Sie ihn gemäß Ihrem URL-Pfad aus, um den Account-Index darzustellen

Grüße

Ich sehe viele Implementierungen, die clientseitige Änderungen haben, um Session-ID-Cookies zu manipulieren. Im Allgemeinen sollten die Session-ID-Cookies jedoch HttpOnly sein, damit java-script nicht darauf zugreifen kann. Andernfalls kann es zu Session Hijack through XSS kommen

Hinweis: Die Lösung muss hier in der Anwendungsentwicklungsphase durchgeführt werden. Es wäre schwierig, dies später zu konstruieren.

Verwenden Sie ein verstecktes Feld, um die Sitzungskennung zu übergeben .

Damit dies funktioniert, muss jede Seite ein Formular enthalten:

 

Jede Aktion auf Ihrer Seite, einschließlich Navigation, POST das Formular zurück (Einstellung der action als angemessen). Bei “unsicheren” Anfragen können Sie einen anderen Parameter angeben, der zB einen JSON-Wert der zu übermittelnden Daten enthält:

   

Da es keine Cookies gibt, ist jeder Tab unabhängig und kennt keine anderen Sitzungen im selben Browser.

Viele Vorteile, besonders in Sachen Sicherheit:

  • Kein Vertrauen in JavaScript oder HTML5.
  • Inhärent schützt gegen CSRF .
  • Kein Vertrauen in Cookies, schützt also vor POODLE .
  • Nicht anfällig für Sitzungsfixierung .
  • Kann die Verwendung der Zurück-Schaltfläche verhindern, was wünschenswert ist, wenn Benutzer einem festgelegten Pfad durch Ihre Site folgen sollen (was Logikerrors bedeutet, die manchmal von Out-of-Order-Anfragen angegriffen werden können).

Einige Nachteile:

  • Die functionalität der Zurück-Taste kann erwünscht sein.
  • Nicht sehr effektiv mit Caching, da jede Aktion ein POST ist.

Weitere Informationen hier .

Ich habe das folgendermaßen getriggers:

  • Ich habe dem Fenster einen Namen zugewiesen, der der Verbindungsressource gleich ist.
  • Plus 1 zum Löschen in Cookie für die Verbindung zu speichern.
  • Ich habe eine function erstellt, um alle xmloutput Antwort zu erfassen und Sid zuzuweisen und loszuwerden Cookie im JSON-Format. Ich mache das für jeden window.name.

hier der Code:

 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); } 

Ich hoffe dir zu helfen

Wenn jede Registerkarte einen anderen Ablauf in Ihrer Anwendung ausführt und das Mischen beider Flüsse zu Problemen führt, ist es besser, Ihre Sitzungsobjekte zu “regionalisieren”, sodass jeder Ablauf eine andere Region der Sitzung verwendet

Diese Region kann einfach durch verschiedene Präfixe für jeden Fluss implementiert werden, oder das Sitzungsobjekt enthält mehrere Zuordnungen (eine für jeden Ablauf) und Sie verwenden diese Zuordnungen anstelle von Sitzungsattributen. Am besten wäre es jedoch, Ihre Sitzungsklasse zu erweitern benutze es stattdessen.