Wie kann man Sitzungen in Browser-Registerkarten unterscheiden?

135

In einer in Java implementierten Webanwendung mit JSP und Servlets; Wenn ich Informationen in der Benutzersitzung speichere, werden diese Informationen von allen Registerkarten desselben Browsers freigegeben. Wie können Sitzungen in den Browser-Registerkarten unterschieden werden? In diesem Beispiel:

<%@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>

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

Vielen Dank.

Oriol Terradas
quelle
1
Dies ist eine Sache, die der Benutzer tun muss: Öffnen Sie den IE, klicken Sie auf "Datei-> Neue Sitzung"
Stefan Steiger
3
@Quandary, Ihre Lösung ist keine generische Lösung (in anderen Browsern funktioniert sie nicht) und vor allem nicht benutzerfreundlich (die Benutzer wissen nichts über Sitzungen).
Oriol Terradas
2
Einige Leute scheinen sich nicht vorstellen zu können, was der Zweck davon ist. Die Problemdomäne ist fast jede Situation, in der Sie unterschiedliche "Ansichten" Ihrer Website zulassen möchten. Sobald der Benutzer mehr als eine Ansicht Ihrer Website haben kann, dauert es unweigerlich lange (oder versucht versehentlich), gleichzeitig auf zwei verschiedene Ansichten zuzugreifen. Beispiele hierfür sind: zeitliche Versionierung (Wechseln Sie zur Website, wie sie zu einem bestimmten Zeitpunkt in der Vergangenheit vorhanden war); Sandboxing (Änderungen an der Website vornehmen, die andere noch nicht sehen können); rollenbasierte Ansichten (siehe, wie die Website für weniger privilegierte Benutzer aussieht); usw.
Ron Burk

Antworten:

92

Sie können HTML5 SessionStorage (window.sessionStorage) verwenden. Sie generieren eine zufällige ID und speichern sie im Sitzungsspeicher pro Browser-Registerkarte. Dann hat jeder Browser-Tab seine eigene ID.

Mit sessionStorage gespeicherte Daten bleiben nicht auf allen Browser-Registerkarten erhalten, auch wenn zwei Registerkarten Webseiten desselben Domänenursprungs enthalten. Mit anderen Worten, Daten in sessionStorage beschränken sich nicht nur auf die Domäne und das Verzeichnis der aufrufenden Seite, sondern auch auf die Browser-Registerkarte, in der die Seite enthalten ist. Vergleichen Sie dies mit Sitzungscookies, bei denen Daten von Registerkarte zu Registerkarte erhalten bleiben.

Gonzalo Gallotti
quelle
7
Aus Dokumenten: "Mit sessionStorage gespeicherte Daten bleiben nicht auf allen Browser-Registerkarten erhalten, auch wenn zwei Registerkarten Webseiten desselben Domänenursprungs enthalten. Mit anderen Worten, Daten in sessionStorage beschränken sich nicht nur auf die Domäne und das Verzeichnis der aufrufenden Seite, sondern auch auf diese die Browser-Registerkarte, in der die Seite enthalten ist. Vergleichen Sie dies mit Sitzungscookies, die Daten von Registerkarte zu Registerkarte beibehalten. " Einfache Tests bestätigen dieses Verhalten in Chrome und FF.
Jswanson
21
Beachten Sie, dass die ID bei Verwendung der Chrome-Funktion "Registerkarte duplizieren" dupliziert wird. Dies ist im Allgemeinen kein Problem, sollte aber durchdacht werden.
JosiahDaniels
Außer wenn Sie eine Registerkarte in Chrome oder Firefox "duplizieren". In diesem Fall wird SessionStorage kopiert.
Tiago Freitas Leal
@ Gonzalo Gallotti: Und wie hilft mir das, wenn die Sitzung serverseitig ist? )))
Stefan Steiger
@StefanSteiger. Anschließend können Sie die BrowserTab-ID (im Sitzungsspeicher gespeichert) mit Ihrem Ajax-Aufruf senden. Auf der Serverseite benötigen Sie eine benutzerdefinierte Logik, da die WebSession dieselbe ist. Sie können jedoch eine HashMap mit Sitzungsobjekten nach Registerkarte erstellen.
Gonzalo Gallotti
23

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

  • Kekse. Die sauberere und populärere Methode, aber es bedeutet, dass alle Browser-Registerkarten und -Fenster eines Benutzers die Sitzung gemeinsam nutzen - IMO ist dies in der Tat wünschenswert, und ich würde mich sehr über eine Site ärgern, die mich dazu veranlasst hat, mich für jede neue Registerkarte anzumelden, seit ich Verwenden Sie Tabs sehr intensiv
  • URL neu schreiben. An jede URL auf der Site wird eine Sitzungs-ID angehängt. Dies ist mehr Arbeit (Sie müssen überall dort etwas tun, wo Sie einen Site-internen Link haben), ermöglicht jedoch separate Sitzungen auf verschiedenen Registerkarten, obwohl über den Link geöffnete Registerkarten die Sitzung weiterhin gemeinsam nutzen. Dies bedeutet auch, dass sich der Benutzer immer anmelden muss, wenn er zu Ihrer Site kommt.

Was versuchst du überhaupt zu tun? Warum sollten Registerkarten separate Sitzungen haben? Vielleicht gibt es eine Möglichkeit, Ihr Ziel zu erreichen, ohne überhaupt Sitzungen zu verwenden?

Bearbeiten: Zum Testen können andere Lösungen gefunden werden (z. B. das 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 ein Login mehrere Rollen haben kann. Sie müssen entscheiden, ob dies, das Umschreiben von URLs oder das einfache Leben mit der aktuellen Situation akzeptabler ist, da es einfach nicht möglich ist, Browser-Registerkarten mit Cookie-basierten Sitzungen separat zu behandeln.

Michael Borgwardt
quelle
6
Es ist für eine große Anwendung, die die Benutzerinformationen und die Umgebung behält. Wenn sich jemand mit unterschiedlichen Benutzern in unterschiedlichen Registerkarten, zum Testen oder für unterschiedliche Rollen anmeldet, kreuzt er Informationen von Registerkarten.
Oriol Terradas
Nur ein sehr spätes Add-On, warum: Weil ich das wissen muss, um zu wissen, auf welche Seite meiner Website sich ein Benutzer beispielsweise konzentriert, und nicht nur, dass er von Seite zu Seite gegangen ist ( stattdessen gingen sie von Tab zu Tab).
Oliver Williams
16

Die Javascript-Eigenschaft window.name ist das einzige Element, das über die Tabulatoraktivität hinweg erhalten bleibt, jedoch unabhängig bleiben kann (anstelle von URL-Guff).

Dave Bish
quelle
3
window.sessionStorage tut auch
felickz
3
Vorsicht, da der Sitzungsspeicher in einen neuen Tab kopiert wird, wenn der Benutzer "In neuem Tab öffnen" wählt. Ich wünschte, ich hätte einen Link für Details, aber siehe: bugzilla.mozilla.org/show_bug.cgi?id=818389
felickz
2
Beachten Sie, dass das, was Sie in der Einstellung window.name speichern, in anderen Domänen weiterhin verfügbar ist, wenn der Benutzer zu anderen Seiten auf derselben Registerkarte wechselt.
Nakib
15

Das solltest du 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. Verwenden Sie eine ID für die gleiche Sitzungs-ID (keine Sitzungs-ID, die nicht funktioniert) und übergeben Sie sie in jeder URL.

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

DR. böse
quelle
9
Es ist für eine große Anwendung, die die Benutzerinformationen und die Umgebung behält. Wenn sich jemand mit unterschiedlichen Benutzern in unterschiedlichen Registerkarten, zum Testen oder für unterschiedliche Rollen anmeldet, kreuzt er Informationen von Registerkarten.
Oriol Terradas
38
alte Antwort Ich weiß, aber Google Mail ermöglicht es Ihnen, verschiedene Konten pro Tab zu haben und es ist keine "völlig unbrauchbare Anwendung"
George
2
@ George, die Antwort stimmt immer noch, und für Ihr Beispiel sehen Sie in der URL-Nummer den Index der in Cookies gespeicherten Konten. Google Mail speichert nur alle Cookies und wählt eines entsprechend der URL aus.
Mhmd
5
Sie sind sich nicht sicher, ob die Antwort immer noch richtig ist. Sie können es eindeutig tun. Google Mail macht es. Wie es funktioniert, mag nicht elegant sein, aber es funktioniert und das ist wichtig
George
2
Alte Antwort, aber ich darf hinzufügen, dass WhatsApp und Telegramm nicht zulassen, dass zwei Registerkarten gleichzeitig geöffnet sind. Das macht sie nicht unbrauchbar
Charlie
13

Ich habe mir eine neue Lösung ausgedacht, die ein wenig Overhead hat, aber anscheinend als Prototyp funktioniert. Eine Annahme ist, dass Sie sich für die Anmeldung in einer Ehrensystemumgebung befinden. Dies kann jedoch angepasst werden, indem Sie beim Wechseln der Registerkarte erneut ein Kennwort anfordern.

Verwenden Sie localStorage (oder ein gleichwertiges Element) und das HTML5-Speicherereignis, um festzustellen, wann eine neue Browserregisterkarte gewechselt hat, welcher Benutzer aktiv ist. Erstellen Sie in diesem Fall ein Ghost-Overlay mit der Meldung, dass Sie das aktuelle Fenster nicht verwenden können (oder deaktivieren Sie das Fenster auf andere Weise vorübergehend, damit es nicht so auffällig wird.) Wenn das Fenster wieder den Fokus erhält, senden Sie eine AJAX-Anforderungsprotokollierung der Benutzer wieder in.

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 einen Anruf nach einer Verzögerung hatten), es sei denn Sie führen zuvor manuell einen AJAX-Neuanmeldeanruf durch. Alles, was Sie wirklich tun müssen, ist, zuerst Ihre AJAX-Funktion überprüfen zu lassen, um sicherzustellen, dass localStorage.currently_logged_in_user_id === window.yourAppNameSpace.user_id. Wenn nicht, melden Sie sich zuerst über AJAX an.

Ein weiterer Grund sind die Rennbedingungen: Wenn Sie das Fenster schnell genug wechseln können, um es zu verwirren, erhalten Sie möglicherweise eine relogin1-> relogin2-> ajax1-> ajax2-Sequenz, wobei ajax1 in der falschen Sitzung erstellt wird. Umgehen Sie dies, indem Sie AJAX-Anmeldeanforderungen auf ein Array übertragen und dann speichern und vor dem Ausgeben einer neuen Anmeldeanforderung alle aktuellen Anforderungen abbrechen.

Das letzte Problem, auf das Sie achten müssen, sind Fensteraktualisierungen. Wenn jemand das Fenster aktualisiert, während eine AJAX-Anmeldeanforderung aktiv, aber nicht abgeschlossen ist, wird es im Namen der falschen Person aktualisiert. In diesem Fall können Sie das nicht standardmäßige Ereignis "Beforeunload" verwenden, um den Benutzer vor einer möglichen Verwechslung zu warnen und ihn aufzufordern, auf "Abbrechen" zu klicken, während eine AJAX-Anmeldeanforderung erneut ausgegeben wird. Die einzige Möglichkeit, dies zu verpfuschen, besteht darin, vor Abschluss der Anforderung auf OK zu klicken (oder versehentlich die Eingabetaste / Leertaste zu drücken, da OK - leider für diesen Fall - die Standardeinstellung ist). Es gibt andere Möglichkeiten, diesen Fall zu behandeln, z Erkennen von Drücken von F5 und Strg + R / Alt + R, was in den meisten Fällen funktioniert, jedoch durch Neukonfiguration der Tastenkombination oder alternative Verwendung des Betriebssystems vereitelt werden kann. Dies ist jedoch in der Realität ein Randfall. und die Worst-Case-Szenarien sind nie so schlimm: In einer Honor-System-Konfiguration würden Sie als falsche Person angemeldet sein (aber Sie können deutlich machen, dass dies der Fall ist, indem Sie Seiten mit Farben, Stilen, prominent angezeigten Namen personalisieren, etc.); In einer Kennwortkonfiguration liegt die Verantwortung bei der letzten Person, die ihr Kennwort eingegeben hat, um sich abgemeldet oder ihre Sitzung freigegeben zu haben. Wenn diese Person tatsächlich der aktuelle Benutzer ist, liegt kein Verstoß vor.

Am Ende haben Sie jedoch eine Anwendung für einen Benutzer pro Registerkarte, die (hoffentlich) genau so funktioniert, wie sie sollte, ohne dass Sie unbedingt Profile einrichten, den IE verwenden oder URLs neu schreiben müssen. Stellen Sie jedoch sicher, dass Sie auf jeder Registerkarte deutlich machen, wer auf dieser Registerkarte angemeldet ist.

Kev
quelle
6
+1, weil du dir die Zeit genommen hast, das wirklich durchzudenken! :-) Wenn man sich all die Vorbehalte ansieht, weiß man einfach, dass es eine schlechte Idee ist. Meine Lehren aus diesem Zeug sind, wirklich zu verstehen, welche Daten in Sitzungen eingehen sollen und welche nicht.
Peter
10

Wir hatten dieses Problem und haben es sehr einfach gelöst. Ich meine einfach, weil keine Programmierung erforderlich ist. Wir wollten, dass sich ein Benutzer bei mehreren Konten innerhalb desselben Browserfensters anmeldet, ohne dass die Sitzungen in Konflikt geraten.

Die Lösung waren also zufällige Subdomänen.

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

Deshalb haben wir unseren Systemadministrator gebeten, die SSL-Zertifikate für * .abc.com anstatt abc.com zu konfigurieren. Mit wenig Codeänderung wird ein Benutzer jedes Mal, wenn er versucht, sich anzumelden, auf einer Registerkarte mit einer zufälligen Subdomain-Nummer angemeldet. So kann jede Registerkarte unabhängig eine eigene Sitzung haben. Um Konflikte zu vermeiden, haben wir die Zufallszahl mit einem Hash oder md5 der Benutzer-ID entwickelt.

user3534653
quelle
3
Dies scheint eine clevere Alternative zum Umschreiben von URLs zu sein. Sie erhalten die gewünschte Variable (Sitzungs-ID) an einem HTTP-konformen Ort, der sichtbar, aber nicht aufdringlich ist. Nissen, die mir in den Sinn kommen: 1) Sie benötigen natürlich einen Platzhalter für DNS. 2) Ihre gesamte Website muss absolute URLs vermeiden, die den Benutzer zurück zur (z. B.) Subdomain "www" leiten würden. 3) Sie möchten wahrscheinlich Webcrawler fernhalten , aber dies ist wahrscheinlich eine Private-Web-Situation, so dass dies bereits geschehen kann. Danke, dass du das geteilt hast!
Ron Burk
@ user3534653: Ich mag den Ansatz. Aber Sie sagten "keine Programmierung erforderlich". Dann sagen Sie "mit wenig Codeänderung". Also wirklich, eine kleine Codeänderung programmiert nicht? ;) Dieser Ansatz funktioniert möglicherweise auch nicht, wenn Sie mehrere Anwendungen mit kanonischen Links haben, bei denen die Domäne fest codiert / konfiguriert ist (kanonisch).
Stefan Steiger
5

Ich werde hier ehrlich sein. . . Alles oben Genannte mag wahr sein oder auch nicht, aber es scheint alles viel zu kompliziert zu sein oder es geht nicht darum zu wissen, welche Registerkarte serverseitig verwendet wird.

Manchmal müssen wir Occams Rasiermesser anwenden.

Hier ist der Ansatz des Occam: (Nein, ich bin kein Occam, er starb 1347)

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

2) Setzen Sie auf jeder Seite, die Sie haben (verwenden Sie eine globale Datei oder etwas anderes), einfach Code ein, um das Fokusereignis und / oder das Mouseover-Ereignis zu erkennen. (Ich werde jquery für diesen Teil verwenden, um das Schreiben von Code zu vereinfachen.)

3) Setzen Sie in Ihrer Fokus- (und / oder Mouseover-) Funktion ein Cookie mit dem Namen window.name

4) Lesen Sie diesen Cookie-Wert von Ihrer Serverseite, wenn Sie tabulatorspezifische Daten lesen / schreiben müssen.

Client-Seite:

//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 Zwecke)

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

Getan.

Mike A.
quelle
1
Ich mag Ihre vereinfachte Antwort und Occams Rasiermesserreferenz sehr. Ich wollte nur überprüfen, ob diese Lösung noch für Sie funktioniert.
Jeff Marino
1
Es ist zu beachten, dass dieser Ansatz nicht funktionieren würde, wenn das Aktualisieren der Seite ihre Sitzung beibehalten sollte. Der andere vorgeschlagene Ansatz in einer anderen Antwort zur Verwendung von window.sessionStorage erscheint mir vernünftiger.
Rosenfeld
@quijibo Funktioniert immer noch perfekt in meiner Anwendung, ja. Das Aktualisieren der Seite kann für einige Browser zutreffen. Die Verwendung von window.sessionStorage kann das Problem möglicherweise beheben. Ich habe es nicht ausprobiert
Mike A.
3
Was ist die Funktion "se_appframe ()"?
AndreMiranda
Was ist se_appframe ?
Kiquenet
2

Sie können das Umschreiben von Links verwenden, um eine eindeutige Kennung an alle Ihre URLs anzuhängen, wenn Sie mit einer einzelnen Seite beginnen (z. B. index.html / jsp / Whatever). Der Browser verwendet für alle Ihre Registerkarten dieselben Cookies, sodass alles, was Sie in Cookies einfügen, nicht eindeutig ist.

Bombe
quelle
2
Ich denke, das Umschreiben von Links zum Codieren von Sitzungen ist mühsam und fehleranfällig. Ich habe eine große Anwendung mit vielen Links, ich brauche eine transparente Lösung oder einfach zu implementieren.
Oriol Terradas
2

Ich denke, Sie möchten wahrscheinlich den Navigationsstatus über Registerkarten hinweg beibehalten und nicht speziell eine einzelne Sitzung pro Registerkarte erstellen. Dies ist genau das, was das Seam-Framework mit seinem Konversationsumfang / -kontext erreicht. Ihre Implementierung basiert auf der Tatsache, dass eine Konversations-ID mit jeder Anforderung weitergegeben wird und den Begriff einer Konversation auf der Serverseite erzeugt, die zwischen einer Sitzung und einer Anforderung liegt. Es ermöglicht die Steuerung des Navigationsflusses und die Statusverwaltung.

Obwohl dies hauptsächlich für JSF gedacht ist, schauen Sie nach, ob Sie hier einige Ideen finden können: http://docs.jboss.org/seam/latest/reference/en-US/html_single/#d0e3620

lsoliveira
quelle
1

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

Stephen
quelle
1

Ich habe kürzlich mithilfe von Cookies eine Lösung für dieses Problem entwickelt. Hier ist ein Link zu meiner Lösung. Ich habe auch Beispielcode für die Lösung mit ASP.NET eingefügt. Sie sollten diesen bei Bedarf an JSP oder Servelets anpassen können.

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

Sarit Kommineni
quelle
1

Hinweis: Die Lösung hier muss in der Phase des Anwendungsdesigns erfolgen. Es wäre schwierig, dies später zu konstruieren.

Verwenden Sie ein verstecktes Feld, um die Sitzungskennung weiterzugeben .

Damit dies funktioniert, muss jede Seite ein Formular enthalten:

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

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

</form>

Bei jeder Aktion auf Ihrer Seite, einschließlich der Navigation, wird das Formular zurückgeschickt (je actionnach Bedarf). Für "unsichere" Anforderungen können Sie einen anderen Parameter einschließen, der beispielsweise einen JSON-Wert der zu übermittelnden Daten enthält:

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

Da keine Cookies vorhanden sind, ist jede Registerkarte unabhängig und kennt keine anderen Sitzungen im selben Browser.

Viele Vorteile, insbesondere in Bezug auf Sicherheit:

  • Keine Abhängigkeit von JavaScript oder HTML5.
  • Schützt von Natur aus vor CSRF .
  • Kein Vertrauen in Cookies, schützt also vor POODLE .
  • Nicht anfällig für Sitzungsfixierung .
  • Kann die Verwendung von Zurück-Schaltflächen verhindern. Dies ist wünschenswert, wenn Benutzer einem festgelegten Pfad durch Ihre Site folgen sollen (was bedeutet, dass Logikfehler, die manchmal von nicht in der Reihenfolge befindlichen Anforderungen angegriffen werden können, verhindert werden können).

Einige Nachteile:

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

Weitere Informationen hier .

SilverlightFox
quelle
1

Ich habe dies folgendermaßen gelöst:

  • Ich habe dem Fenster einen Namen zugewiesen. Dieser Name entspricht der Verbindungsressource.
  • plus 1, um im Cookie gespeicherte Daten für die Verbindung zu entfernen.
  • Ich habe eine Funktion erstellt, um alle xmloutput-Antworten zu erfassen und Cookies im json-Format sid und rid zuzuweisen. Ich mache das für jeden Fensternamen.

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

Deutscher Sanchez
quelle
0

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

Nachdem ich diese Antworten gelesen hatte, insbesondere die von Michael Borgwardt, erkannte ich den Arbeitsablauf, der existieren muss:

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

Dies löst das Problem, dass Benutzer "Daten eines anderen Benutzers" in ihrer Sitzung sehen. Sie sehen nicht wirklich die Daten eines anderen Benutzers in ihrer Sitzung, sondern die Daten der einzigen Sitzung, die sie geöffnet haben. Dies führt eindeutig zu einigen interessanten Daten, da einige Vorgänge einige Sitzungsdaten überschreiben und andere nicht, sodass Sie eine Kombination von Daten in dieser einzelnen Sitzung haben.

Nun, um das Testproblem zu beheben. Der einzig praktikable Ansatz wäre die Nutzung von Präprozessor-Richtlinien , um zu bestimmen, ob Sitzungen ohne Cookies verwendet werden sollten. Indem ich eine bestimmte Konfiguration für eine bestimmte Umgebung einbaue, kann ich einige Annahmen über die Umgebung und deren Verwendung treffen. Auf diese Weise könnte ich technisch gesehen zwei Benutzer gleichzeitig anmelden, und der Tester könnte mehrere Szenarien aus derselben Browsersitzung testen, ohne sich jemals von einer dieser Serversitzungen abzumelden.

Dieser Ansatz weist jedoch einige schwerwiegende Einschränkungen auf. Nicht zuletzt ist die Tatsache, dass das, was der Tester testet, nicht das ist , was in der Produktion laufen wird.

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

Mike Perrenoud
quelle
0

Speichern des Zeitstempels in window.sessionStorage, falls er noch nicht festgelegt ist. Dies gibt einen eindeutigen Wert für jede Registerkarte (auch wenn die URLs identisch sind).

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

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

Hoffe das hilft.

Gast
quelle
1
Dies ist wahrscheinlich in Ordnung, aber theoretisch unsicher. Einige Betriebssysteme (z. B. Windows) weisen eine sehr grobe Zeitstempelgranularität auf. Dies bedeutet, dass Sie den Zeitstempel möglicherweise mehrmals nachschlagen und denselben Wert zurückerhalten. Wenn Sie einen Browser nach einem Absturz erneut öffnen und alle Registerkarten gleichzeitig wieder öffnen, erhalten sie möglicherweise denselben Zeitstempel.
Gili
0
How to differ sessions in browser-tabs?

Der einfachste Weg, Sitzungen in Browser-Registerkarten zu unterscheiden, besteht darin, Ihrer bestimmten Domain das Setzen von Cookies zu untersagen. Auf diese Weise können Sie separate Sitzungen auf separaten Registerkarten durchführen. Angenommen, Sie verbieten Cookies von dieser Domain: www.xyz.com. Sie öffnen Tab 1, melden sich an und beginnen zu surfen. Dann öffnen Sie Tab 2 und können sich entweder als derselbe oder als ein anderer Benutzer anmelden. In beiden Fällen haben Sie eine von Tab 1 getrennte Sitzung. Und so weiter.

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

Kingz
quelle
0

Sie müssen tun

1- Speichern Sie ein Cookie für die Kontenliste

2- Optional können Sie ein Cookie für das Standard-Cookie speichern

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

4- Geben Sie in die URL etwas ein, das den Kontenindex darstellt, und wenn nicht, wählen Sie den Standardindex wie google mail domain.com/0/some-url >> 0 aus. Stellen Sie hier den Kontenindex dar. Möglicherweise müssen Sie auch wissen, wie es geht benutze urlwrite

5- Wenn Sie ein Cookie auswählen, wählen Sie es entsprechend Ihrem URL-Pfad aus, der den Kontoindex darstellt

Grüße

Mhmd
quelle
0

Ich sehe viele Implementierungen, die clientseitige Änderungen aufweisen, um Sitzungs-ID-Cookies zu manipulieren. Im Allgemeinen sollten Sitzungs-ID-Cookies jedoch nur HttpOnly sein, damit Java-Script nicht darauf zugreifen kann, da dies sonst zu Session Hijack über XSS führen kann

vasa.v03
quelle
0

Wenn auf jeder Registerkarte ein anderer Flow in Ihrer Anwendung ausgeführt wird und das Mischen beider Flows Probleme verursacht, ist es besser, Ihre Sitzungsobjekte zu "regionalisieren", damit jeder Flow einen anderen Bereich der Sitzung verwendet

Diese Region kann so einfach implementiert werden, dass für jeden Flow unterschiedliche Präfixe vorhanden sind, oder das Sitzungsobjekt enthält mehrere Zuordnungen (eine für jeden Ablauf), und Sie verwenden diese Zuordnungen anstelle von Sitzungsattributen. Am besten erweitern Sie jedoch Ihre Sitzungsklasse und benutze es stattdessen.

hussein.g
quelle