Jak rozróżnić sesje na kartach przeglądarki?

135

W aplikacji internetowej zaimplementowanej w Javie przy użyciu JSP i Servletów; jeśli przechowuję informacje w sesji użytkownika, informacje te są udostępniane ze wszystkich zakładek tej samej przeglądarki. Jak rozróżnić sesje w kartach przeglądarki? W tym przykładzie:

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

Skopiuj ten kod do strony jsp ( testpage.jsp), wdróż ten plik w istniejącym kontekście aplikacji internetowej na serwerze (używam Apache Tomcat), następnie otwórz przeglądarkę (FF, IE7 lub Opera) używając poprawnego adresu URL ( localhost/context1/testpage.jsp), wpisz swoje imię i nazwisko w polu wejściowym i prześlij formularz. Następnie otwórz nową kartę w tej samej przeglądarce, a wtedy możesz zobaczyć swoje imię (pobierz z sesji) na nowej karcie. Uważaj na pamięć podręczną przeglądarki, czasami wydaje się, że tak się nie dzieje, ale jest w pamięci podręcznej, odśwież drugą kartę.

Dzięki.

Oriol Terradas
źródło
1
To jest rzecz, którą musi zrobić użytkownik: Otwórz IE, kliknij "Plik-> Nowa sesja"
Stefan Steiger
3
@Quandary, Twoje rozwiązanie nie jest rozwiązaniem ogólnym (w innych przeglądarkach nie działa) i, co najważniejsze, nie jest przyjazne dla użytkownika (użytkownicy nie wiedzą o sesjach).
Oriol Terradas
2
Niektórzy ludzie nie potrafią sobie wyobrazić, jaki jest tego cel. Domena, w której występuje problem, to prawie każda sytuacja, w której chcesz zezwolić na różne „widoki” witryny internetowej. Gdy użytkownik może mieć więcej niż jedno wyświetlenie Twojej witryny, nieuchronnie długo (lub przypadkowo próbuje) uzyskać dostęp do dwóch różnych widoków w tym samym czasie. Przykłady obejmują: tymczasowe przechowywanie wersji (przełącz na przeglądanie strony internetowej w takiej postaci, w jakiej istniała w pewnym momencie w przeszłości); sandboxing (wprowadzanie zmian w witrynie, której inni jeszcze nie widzą); widoki oparte na rolach (zobacz, jak witryna wygląda dla mniej uprzywilejowanych użytkowników); itd.
Ron Burk,

Odpowiedzi:

92

Możesz użyć HTML5 SessionStorage (window.sessionStorage). Wygenerujesz losowy identyfikator i zapiszesz w pamięci sesji na karcie przeglądarki. Wtedy każda karta przeglądarki ma swój własny identyfikator.

Dane przechowywane przy użyciu sessionStorage nie są przechowywane na kartach przeglądarki, nawet jeśli dwie karty zawierają strony internetowe z tego samego pochodzenia domeny. Innymi słowy, dane wewnątrz sessionStorage są ograniczone nie tylko do domeny i katalogu strony wywołującej, ale do zakładki przeglądarki, w której znajduje się strona. Porównaj to z plikami cookie sesji, które przechowują dane z karty na kartę.

Gonzalo Gallotti
źródło
7
From docs: „Dane przechowywane przy użyciu sessionStorage nie są zachowywane na kartach przeglądarki, nawet jeśli dwie karty zawierają strony internetowe z tego samego źródła domeny. Innymi słowy, dane wewnątrz sessionStorage są ograniczone nie tylko do domeny i katalogu strony wywołującej, ale karta przeglądarki, w której znajduje się strona. Porównaj to z plikami cookie sesji, które utrwalają dane między kolejnymi kartami. " Proste testy potwierdzają to zachowanie w Chrome i FF.
jswanson
21
Pamiętaj, że identyfikator zostanie zduplikowany podczas korzystania z funkcji „Duplikuj kartę” w Chrome. Na ogół nie stanowi to problemu, ale należy to przemyśleć.
JosiahDaniels
Z wyjątkiem sytuacji, gdy „zduplikujesz” kartę w przeglądarce Chrome lub Firefox. W takim przypadku SessionStorage jest kopiowany.
Tiago Freitas Leal
@Gonzalo Gallotti: A jak mi to pomoże, jeśli sesja jest po stronie serwera? )))
Stefan Steiger
@StefanSteiger. Następnie możesz wysłać identyfikator BrowserTab (zapisany w pamięci sesji) za pomocą połączenia Ajax. Po stronie serwera będziesz potrzebować niestandardowej logiki, ponieważ sesja internetowa jest taka sama. Ale możesz utworzyć HashMap z obiektami sesji według zakładki.
Gonzalo Gallotti
23

Musisz zdać sobie sprawę, że sesje po stronie serwera są sztucznym dodatkiem do HTTP. Ponieważ protokół HTTP jest bezstanowy, serwer musi w jakiś sposób rozpoznać, że żądanie należy do określonego użytkownika, którego zna i dla którego ma sesję. Można to zrobić na dwa sposoby:

  • Ciasteczka. Czystsza i popularniejsza metoda, ale oznacza, że ​​wszystkie karty przeglądarki i okna jednego użytkownika współdzielą sesję - IMO jest to w rzeczywistości pożądane i byłbym bardzo zirytowany na stronie, która zmusiłaby mnie do logowania się na każdą nową kartę, ponieważ ja używaj tabletek bardzo intensywnie
  • Przepisywanie adresu URL. Każdy adres URL w witrynie ma dołączony identyfikator sesji. Wymaga to więcej pracy (musisz coś zrobić wszędzie tam, gdzie masz link do strony wewnętrznej), ale umożliwia oddzielne sesje w różnych zakładkach, chociaż karty otwarte za pomocą linku nadal będą współdzielić sesję. Oznacza to również, że użytkownik zawsze musi się zalogować, kiedy odwiedza Twoją witrynę.

Co ty właściwie próbujesz zrobić? Dlaczego chcesz, aby karty miały oddzielne sesje? Może jest sposób na osiągnięcie celu bez korzystania z sesji?

Edycja: do testowania można znaleźć inne rozwiązania (na przykład uruchamianie kilku instancji przeglądarki na oddzielnych maszynach wirtualnych). Jeśli jeden użytkownik musi działać w różnych rolach w tym samym czasie, wówczas koncepcja „roli” powinna być obsługiwana w aplikacji, tak aby jeden login mógł mieć kilka ról. Będziesz musiał zdecydować, czy to, używając przepisywania adresów URL, czy po prostu żyjąc w obecnej sytuacji, jest bardziej akceptowalne, ponieważ po prostu nie jest możliwe oddzielne obsługiwanie kart przeglądarki w sesjach opartych na plikach cookie.

Michael Borgwardt
źródło
6
Jest przeznaczony do dużej aplikacji, która przechowuje informacje o użytkowniku i środowisko. Kiedy ktoś loguje się z różnymi użytkownikami w różnych zakładkach, w celu przetestowania lub dla różnych ról, wtedy przecina informacje z zakładek.
Oriol Terradas,
Tylko bardzo późny dodatek wyjaśniający, dlaczego: ponieważ muszę to wiedzieć, aby wiedzieć, na przykład, na której stronie w mojej witrynie koncentruje się użytkownik, a nie tylko, że przeszedł ze strony na stronę ( zamiast tego przechodzili od karty do karty).
Oliver Williams
16

Właściwość window.name Javascript jest jedyną rzeczą, która będzie trwała przez aktywność karty, ale może pozostać niezależna (zamiast guff adresu URL).

Dave Bish
źródło
3
window.sessionStorage również
felickz
3
ostrożnie, ponieważ pamięć sesji jest kopiowana do nowej karty, gdy użytkownik wybierze opcję „Otwórz w nowej karcie” ... szkoda, że ​​nie mam linku do szczegółów, ale zobacz: bugzilla.mozilla.org/show_bug.cgi?id=818389
felickz
2
Należy pamiętać, że to, co zapiszesz w ustawieniu window.name, będzie nadal dostępne w innych domenach, gdy użytkownik przejdzie na inne strony w tej samej karcie.
nakib
15

Nie powinieneś.Jeśli chcesz coś takiego zrobić, musisz albo zmusić użytkownika do korzystania z pojedynczej instancji twojej aplikacji, pisząc adresy URL w locie, użyj identycznego identyfikatora sesji (nie sessionid, to nie zadziała) id i podaj go w każdym adresie URL.

Nie wiem, dlaczego tego potrzebujesz, ale jeśli nie potrzebujesz stworzyć całkowicie bezużytecznej aplikacji, nie rób tego.

dr. zło
źródło
9
Jest przeznaczony do dużej aplikacji, która przechowuje informacje o użytkowniku i środowisko. Kiedy ktoś loguje się z różnymi użytkownikami w różnych zakładkach, w celu przetestowania lub dla różnych ról, wtedy przecina informacje z zakładek.
Oriol Terradas,
38
stara odpowiedź Wiem, ale poczta Google pozwala na posiadanie różnych kont na każdej karcie i nie jest to „całkowicie bezużyteczna aplikacja”
George
2
@George, Odpowiedź wciąż poprawna, a na przykład zobaczysz w adresie URL numer reprezentujący indeks kont przechowywanych w plikach cookie, google mail po prostu przechowuje wszystkie pliki cookie i wybierz jeden zgodnie z adresem URL.
Mhmd,
5
Nie jesteś pewien, czy odpowiedź jest nadal prawidłowa, możesz to zrobić. Gmail to robi. Jeśli chodzi o to, jak to robi, może nie jest eleganckie, ale działa i to jest ważne
George
2
Stara odpowiedź, ale mogę dodać, że Whatsapp i Telegram nie pozwalają na jednoczesne otwarcie dwóch kart. To nie czyni ich bezużytecznymi
Charlie
13

Wymyśliłem nowe rozwiązanie, które ma niewielki narzut, ale wydaje się działać tak daleko, jak prototyp. Jednym z założeń jest to, że jesteś w honorowym środowisku systemowym do logowania, chociaż można to dostosować, żądając ponownie hasła za każdym razem, gdy zmieniasz zakładki.

Użyj localStorage (lub odpowiednika) i zdarzenia magazynu HTML5, aby wykryć, kiedy nowa karta przeglądarki przełączyła aktywnego użytkownika. Kiedy tak się stanie, utwórz nakładkę ducha z komunikatem, że nie możesz używać bieżącego okna (lub w inny sposób tymczasowo wyłącz okno, możesz nie chcieć, aby było tak widoczne). Gdy okno odzyska fokus, wyślij rejestrację żądania AJAX użytkownik z powrotem w.

Jedno zastrzeżenie do tego podejścia: nie możesz mieć żadnych normalnych wywołań AJAX (tj. Tych, które zależą od twojej sesji) w oknie, które nie jest fokusem (np. Jeśli połączenie miało miejsce z opóźnieniem), chyba że wcześniej ręcznie wykonujesz wywołanie ponownego logowania AJAX. Tak naprawdę wszystko, co musisz zrobić, to najpierw sprawdzić funkcję AJAX, aby upewnić się, że localStorage.currently_logged_in_user_id === window.yourAppNameSpace.user_id, a jeśli nie, zaloguj się najpierw przez AJAX.

Innym są warunki wyścigu: jeśli możesz przełączyć okna na tyle szybko, aby zmylić to, możesz skończyć z sekwencją relogin1-> relogin2-> ajax1-> ajax2, z ajax1 tworzonym w niewłaściwej sesji. Aby obejść ten problem, należy wypychać żądania logowania AJAX do tablicy, a następnie przechowywać je w pamięci i przed wydaniem nowego żądania logowania przerwać wszystkie bieżące żądania.

Ostatnią rzeczą, na którą należy zwrócić uwagę, jest odświeżanie okien. Jeśli ktoś odświeży okno, gdy masz aktywne, ale nie ukończone żądanie logowania AJAX, zostanie ono odświeżone w imieniu niewłaściwej osoby. W takim przypadku możesz użyć niestandardowego zdarzenia beforeunload, aby ostrzec użytkownika o potencjalnym pomyłce i poprosić go o kliknięcie Anuluj, w międzyczasie ponownie wysyłając żądanie logowania AJAX. Wtedy jedynym sposobem, w jaki mogą to spartaczyć, jest kliknięcie OK przed zakończeniem żądania (lub przypadkowe naciśnięcie klawisza Enter / spacja, ponieważ OK jest - niestety w tym przypadku - domyślnym). Istnieją inne sposoby obsługi tego przypadku, takie jak wykrywanie naciśnięć F5 i Ctrl + R / Alt + R, które będą działać w większości przypadków, ale mogą zostać udaremnione przez rekonfigurację skrótów klawiaturowych użytkownika lub alternatywne użycie systemu operacyjnego. W rzeczywistości jest to jednak ostry przypadek, a najgorsze scenariusze nigdy nie są takie złe: w konfiguracji systemu honorowego byłbyś zalogowany jako niewłaściwa osoba (ale możesz to wyjaśnić, personalizując strony za pomocą kolorów, stylów, wyraźnie wyświetlanych nazw, itp.); w konfiguracji hasła obowiązek wylogowania lub udostępnienia sesji spoczywa na ostatniej osobie, która wprowadziła hasło, lub jeśli ta osoba jest faktycznie bieżącym użytkownikiem, nie ma naruszenia.

Ale w końcu masz aplikację z jednym użytkownikiem na kartę, która (miejmy nadzieję) działa tak, jak powinna, bez konieczności konfigurowania profili, używania IE lub przepisywania adresów URL. Upewnij się, że na każdej karcie jest oczywiste, kto jest zalogowany na tej karcie, chociaż ...

Kev
źródło
6
+1, ponieważ poświęciłeś trochę czasu, żeby to przemyśleć! :-) Patrząc na wszystkie zastrzeżenia, po prostu wiesz, że to zły pomysł. Moje wnioski wyciągnięte z tych rzeczy polegają na tym, aby naprawdę zrozumieć, jakie dane powinny trafiać do sesji, a które nie.
Peter,
10

Mieliśmy ten problem i rozwiązaliśmy go bardzo łatwo. Mam na myśli łatwe, ponieważ nie wymaga programowania. Chcieliśmy pozwolić użytkownikowi zalogować się na wiele kont w tym samym oknie przeglądarki bez kolidowania sesji.

Tak więc rozwiązaniem były przypadkowe subdomeny.

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

Poprosiliśmy więc administratora systemu o skonfigurowanie certyfikatów SSL dla * .abc.com zamiast abc.com. Następnie, przy niewielkiej zmianie kodu, za każdym razem, gdy użytkownik próbuje się zalogować, jest logowany na karcie z losowym numerem subdomeny. więc każda karta może mieć swoją własną sesję niezależnie. Aby uniknąć konfliktów, opracowaliśmy liczbę losową przy użyciu skrótu lub md5 identyfikatora użytkownika.

user3534653
źródło
3
Wydaje się, że jest to sprytna alternatywa dla przepisywania adresów URL. Otrzymujesz żądaną zmienną (identyfikator sesji) w miejscu zgodnym z HTTP, które jest widoczne, ale nie natrętne. Nici, które przychodzą mi do głowy: 1) oczywiście potrzebują symbolu wieloznacznego w DNS, 2) cała witryna musi unikać bezwzględnych adresów URL, które przekierowują użytkownika z powrotem (np.) Do subdomeny „www”, 3) prawdopodobnie chcą uniemożliwić robotom internetowym , ale jest to prawdopodobnie sytuacja w sieci prywatnej, więc można to już zrobić. Dzięki za udostępnienie tego!
Ron Burk,
@ user3534653: Podoba mi się to podejście. Ale powiedziałeś „bez programowania”. Następnie mówisz „z niewielką zmianą kodu”. Więc naprawdę, mała zmiana kodu to nie programowanie? ;) Ponadto to podejście może nie działać, jeśli masz wiele aplikacji z łączami kanonicznymi, w których domena jest zakodowana / skonfigurowana na stałe (kanonicznie).
Stefan Steiger
5

Będę tu szczery. . . wszystko powyżej może, ale nie musi, być prawdą, ale wszystko wydaje się DUŻO zbyt skomplikowane lub nie dotyczy wiedzy, która karta jest używana po stronie serwera.

Czasami musimy zastosować brzytwę Ockhama.

Oto podejście Occam: (nie, nie jestem Occam, zmarł w 1347)

1) przypisz do swojej strony unikalny identyfikator przeglądarki podczas wczytywania. . . wtedy i tylko wtedy, gdy okno nie ma jeszcze identyfikatora (więc użyj prefiksu i wykrywania)

2) na każdej stronie, którą masz (użyj pliku globalnego lub czegoś podobnego), po prostu umieść kod w miejscu, aby wykryć zdarzenie fokusu i / lub zdarzenie najechania myszą. (W tej części użyję jquery, aby ułatwić pisanie kodu)

3) w funkcji fokusu (i / lub najechania myszą) ustaw plik cookie z plikiem window.name

4) odczytaj wartość pliku cookie ze swojego serwera, gdy chcesz odczytać / zapisać dane dotyczące karty.

Strona klienta:

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

po stronie serwera (C # - na przykład do celów)

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

Gotowe.

Mike A.
źródło
1
Bardzo podoba mi się twoja uproszczona odpowiedź i odniesienie do brzytwy Ockhama. Chciałem tylko dokładnie sprawdzić, czy to rozwiązanie nadal działa.
Jeff Marino
1
Warto zauważyć, że gdyby odświeżanie strony zachowywało sesję, takie podejście by nie zadziałało. Inne sugerowane podejście w innej odpowiedzi, polegające na użyciu window.sessionStorage, wydaje mi się bardziej rozsądne.
rosenfeld
@quijibo Nadal działa doskonale w mojej aplikacji, tak. Jeśli chodzi o odświeżanie strony, może być prawdą w przypadku niektórych przeglądarek, użycie window.sessionStorage może rozwiązać problem, nie próbowałem tego
Mike A.
3
Co to jest funkcja „se_appframe ()”?
AndreMiranda
Co to jest se_appframe ?
Kiquenet
2

Możesz użyć przepisywania linków, aby dołączyć unikalny identyfikator do wszystkich swoich adresów URL, zaczynając od pojedynczej strony (np. Index.html / jsp / cokolwiek). Przeglądarka będzie używać tych samych plików cookie dla wszystkich Twoich kart, więc wszystko, co umieścisz w plikach cookie, nie będzie unikatowe.

Bombe
źródło
2
Myślę, że przepisywanie linków do sesji kodowania jest żmudne i podatne na błędy. Mam dużą aplikację, z dużą ilością linków, potrzebuję rozwiązania przejrzystego lub łatwego do wdrożenia.
Oriol Terradas,
2

Myślę, że prawdopodobnie chcesz zachować stan nawigacji między kartami, a nie konkretnie tworzyć pojedynczą sesję na kartę. Dokładnie to osiąga platforma Seam dzięki ich zakresowi / kontekstowi konwersacji. Ich implementacja polega na tym, że identyfikator konwersacji jest propagowany z każdym żądaniem i tworzy pojęcie konwersacji po stronie serwera, czyli coś, co znajduje się między sesją a żądaniem. Pozwala na kontrolę przepływu nawigacji i zarządzanie stanem.

Chociaż jest to głównie skierowane do JSF, spójrz i sprawdź, czy jest to coś, z czego możesz czerpać pomysły: http://docs.jboss.org/seam/latest/reference/en-US/html_single/#d0e3620

lsoliveira
źródło
1

Innym działającym podejściem jest utworzenie unikalnego identyfikatora okna i przechowywanie tej wartości wraz z identyfikatorem sesji w tabeli bazy danych. Identyfikator okna, którego często używam, to liczba całkowita (teraz). Ta wartość jest tworzona, gdy okno jest otwierane i ponownie przypisywane do tego samego okna, jeśli okno jest odświeżane, ponownie ładowane lub przesyłane do siebie. Wartości okien (wejścia) są zapisywane w lokalnej tabeli za pomocą linku. Gdy wymagana jest wartość, jest pobierana z tabeli bazy danych na podstawie odsyłacza id okna / id sesji. Chociaż takie podejście wymaga lokalnej bazy danych, jest praktycznie niezawodne. Korzystanie z tabeli bazy danych było dla mnie łatwe, ale nie widzę powodu, dla którego tablice lokalne nie działałyby tak dobrze.

Stephen
źródło
1

Niedawno opracowałem rozwiązanie tego problemu za pomocą plików cookie. Oto link do mojego rozwiązania. Dołączyłem również przykładowy kod rozwiązania wykorzystujący ASP.NET, powinieneś być w stanie dostosować go do JSP lub Servelets, jeśli potrzebujesz.

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

Sarit Kommineni
źródło
1

Uwaga: tutaj rozwiązanie należy wykonać na etapie projektowania aplikacji. Trudno byłoby to zaprojektować później.

Użyj ukrytego pola, aby przekazać identyfikator sesji .

Aby to działało, każda strona musi zawierać formularz:

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

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

</form>

Każda czynność po Twojej stronie, w tym nawigacja, odsyła formularz z powrotem (ustawiając actionodpowiednio). W przypadku „niebezpiecznych” żądań możesz dołączyć inny parametr, na przykład zawierający wartość JSON przesyłanych danych:

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

Ponieważ nie ma plików cookie, każda karta będzie niezależna i nie będzie miała wiedzy o innych sesjach w tej samej przeglądarce.

Wiele zalet, szczególnie jeśli chodzi o bezpieczeństwo:

  • Nie polegamy na JavaScript ani HTML5.
  • Z natury chroni przed CSRF .
  • Nie polega na plikach cookie, więc chroni przed POODLE .
  • Nie jest podatny na utrwalanie sesji .
  • Może zapobiegać używaniu przycisku Wstecz, co jest pożądane, gdy chcesz, aby użytkownicy podążali ustaloną ścieżką w Twojej witrynie (co oznacza, że ​​można zapobiec błędom logicznym, które czasami mogą być atakowane przez żądania poza kolejnością).

Niektóre wady:

  • Może być potrzebna funkcjonalność przycisku Wstecz.
  • Niezbyt efektywne przy buforowaniu, ponieważ każda akcja to POST.

Więcej informacji tutaj .

SilverlightFox
źródło
1

Rozwiązałem to w następujący sposób:

  • Przypisałem nazwę do okna, ta nazwa jest taka sama jak zasób połączenia.
  • plus 1, aby usunąć zapisane w pliku cookie w celu podłączenia połączenia.
  • Stworzyłem funkcję przechwytującą wszystkie odpowiedzi xmloutput oraz przypisywanie sid i rid do pliku cookie w formacie json. Robię to dla każdego window.name.

tutaj kod:

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

Mam nadzieję, że ci pomogę

Niemiecki Sanchez
źródło
0

Czytałem ten post, ponieważ myślałem, że chcę zrobić to samo. Mam podobną sytuację w przypadku aplikacji, nad którą pracuję. I tak naprawdę to bardziej kwestia testowania niż praktyczności.

Po przeczytaniu tych odpowiedzi, zwłaszcza tych udzielonych przez Michaela Borgwardta, zdałem sobie sprawę z przepływu pracy, który musi istnieć:

  1. Jeśli użytkownik przejdzie do ekranu logowania, sprawdź, czy istnieje sesja. Jeśli taki istnieje, pomiń ekran logowania i wyślij go na ekran powitalny.
  2. Jeśli użytkownik (w moim przypadku) przejdzie do ekranu rejestracji, sprawdź istniejącą sesję. Jeśli taki istnieje, poinformuj użytkownika, że ​​wylogujesz się z tej sesji. Jeśli się zgodzą, wyloguj się i rozpocznij rejestrację.

To rozwiąże problem polegający na tym, że użytkownik widzi dane „innego użytkownika” w swojej sesji. Tak naprawdę nie widzą danych „innego użytkownika” w swojej sesji, tak naprawdę widzą dane z jedynej otwartej sesji. Oczywiście powoduje to pewne interesujące dane, ponieważ niektóre operacje nadpisują niektóre dane sesji, a inne nie, więc masz kombinację danych w tej jednej sesji.

Teraz, aby rozwiązać problem z testowaniem. Jedynym realnym podejściem byłoby wykorzystanie dyrektyw preprocesora w celu określenia, czy należy używać sesji bez plików cookie. Widzisz, budując w określonej konfiguracji dla określonego środowiska, jestem w stanie poczynić pewne założenia dotyczące środowiska i tego, do czego jest używane. To pozwoliłoby mi technicznie na zalogowanie dwóch użytkowników w tym samym czasie, a tester mógłby testować wiele scenariuszy z tej samej sesji przeglądarki bez wylogowywania się z żadnej z tych sesji serwera.

Jednak takie podejście ma poważne zastrzeżenia. Nie mniej ważny jest fakt, że to, co testuje tester, nie jest tym, co zostanie uruchomione w produkcji.

Więc myślę, że muszę powiedzieć, że to ostatecznie zły pomysł.

Mike Perrenoud
źródło
0

Przechowywanie znacznika czasu w window.sessionStorage, jeśli nie jest jeszcze ustawiony. Zapewni to unikalną wartość dla każdej karty (nawet jeśli adresy URL są takie same)

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

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

Mam nadzieję że to pomoże.

Gość
źródło
1
Prawdopodobnie jest to w porządku, ale teoretycznie jest niebezpieczne. Niektóre systemy operacyjne (np. Windows) mają bardzo zgrubną szczegółowość sygnatur czasowych, co oznacza, że ​​możesz wielokrotnie sprawdzać znacznik czasu i odzyskać tę samą wartość. Ponadto, jeśli ponownie otworzysz przeglądarkę po awarii i ponownie otworzy ona wszystkie karty naraz, mogą one otrzymać ten sam znacznik czasu.
Gili
0
How to differ sessions in browser-tabs?

Najprostszym sposobem na zróżnicowanie sesji na kartach przeglądarki jest zablokowanie określonej domenie ustawiania plików cookie. W ten sposób możesz mieć oddzielne sesje z oddzielnych kart. Powiedz, że nie zezwalasz na pliki cookie z tej domeny: www.xyz.com. Otwierasz kartę 1, logujesz się i zaczynasz przeglądać. Następnie otwierasz kartę 2 i możesz zalogować się jako ten sam użytkownik lub inny; tak czy inaczej, sesja będzie oddzielona od karty 1. I tak dalej.

Ale oczywiście jest to możliwe, gdy masz kontrolę nad klientem. W przeciwnym razie zastosowanie powinny mieć rozwiązania zalecane przez ludzi tutaj.

Kingz
źródło
0

będziesz musiał zrobić

1- zapisz plik cookie dla listy kont

2- Opcjonalnie przechowuj plik cookie jako domyślny

3- sklep dla każdego konta z jego indeksem, takim jak acc1, acc2

4- Wpisz w adresie URL coś, co reprezentuje indeks kont, a jeśli nie, wybierzesz domyślny, taki jak google mail domain.com/0/some-url >> 0 tutaj reprezentuje indeks konta również możesz potrzebować wiedzieć jak użyj urlwrite

5- kiedy wybierzesz plik cookie, wybierz go zgodnie ze ścieżką URL reprezentującą indeks konta

pozdrowienia

Mhmd
źródło
0

Widzę wiele implementacji, które mają zmiany po stronie klienta, aby manipulować plikami cookie identyfikatora sesji. Ale ogólnie pliki cookie z identyfikatorem sesji powinny być HttpOnly, więc skrypt java nie może uzyskać dostępu, w przeciwnym razie może to doprowadzić do przejęcia sesji przez XSS

vasa.v03
źródło
0

Jeśli dzieje się tak dlatego, że każda karta będzie uruchamiać inny przepływ w Twojej aplikacji, a mieszanie obu przepływów powoduje problemy, lepiej „regionalizuj” obiekty sesji, aby każdy przepływ używał innego regionu sesji

Ten region można zaimplementować tak prosto, jak posiadanie różnych prefiksów dla każdego przepływu lub obiekt sesji będzie zawierał wiele map (po jednej dla każdego przepływu) i używasz tych map zamiast atrybutów sesji, najlepiej jednak byłoby rozszerzyć klasę sesji i użyj go zamiast tego.

hussein.g
źródło