przeglądarka sessionStorage. udostępniać między kartami?

151

Mam pewne wartości w mojej witrynie, które chcę wyczyścić po zamknięciu przeglądarki. Zdecydowałem sessionStoragesię przechowywać te wartości. Gdy zakładka jest zamknięta, są one rzeczywiście czyszczone i zachowywane, jeśli użytkownik naciśnie klawisz f5; Jeśli jednak użytkownik otworzy łącze w innej karcie, te wartości są niedostępne.

Jak mogę udostępniać sessionStoragewartości na wszystkich kartach przeglądarki w mojej aplikacji?

Przykład użycia: umieść wartość w jakimś miejscu, utrzymuj tę wartość dostępną na wszystkich kartach przeglądarki i wyczyść ją, jeśli wszystkie karty są zamknięte.

if (!sessionStorage.getItem(key)) {
    sessionStorage.setItem(key, defaultValue)
}
Vladimir Gordienko
źródło
9
To dla mnie dziwne, że to zostało zamknięte jako duplikat. Nominacja do ponownego otwarcia. Drugi temat dotyczy „jak komunikować się między wieloma zakładkami”, co brzmi inaczej, a także inaczej, gdy zaczynam czytać inny temat.
KajMagnus
Czy można używać plików cookie? które zachowują się tak domyślnie? (ale rzeczywiście - aby uzyskać i ustawić akcję, będą wymagać dalszej implementacji) developer.mozilla.org/en-US/docs/Web/API/Document/cookie
lingar

Odpowiedzi:

132

Możesz użyć localStorage i jego „storage” eventListener do przenoszenia danych sessionStorage z jednej karty na drugą.

Ten kod musiałby istnieć na WSZYSTKICH kartach. Powinien być wykonywany przed innymi skryptami.

// transfers sessionStorage from one tab to another
var sessionStorage_transfer = function(event) {
  if(!event) { event = window.event; } // ie suq
  if(!event.newValue) return;          // do nothing if no value to work with
  if (event.key == 'getSessionStorage') {
    // another tab asked for the sessionStorage -> send it
    localStorage.setItem('sessionStorage', JSON.stringify(sessionStorage));
    // the other tab should now have it, so we're done with it.
    localStorage.removeItem('sessionStorage'); // <- could do short timeout as well.
  } else if (event.key == 'sessionStorage' && !sessionStorage.length) {
    // another tab sent data <- get it
    var data = JSON.parse(event.newValue);
    for (var key in data) {
      sessionStorage.setItem(key, data[key]);
    }
  }
};

// listen for changes to localStorage
if(window.addEventListener) {
  window.addEventListener("storage", sessionStorage_transfer, false);
} else {
  window.attachEvent("onstorage", sessionStorage_transfer);
};


// Ask other tabs for session storage (this is ONLY to trigger event)
if (!sessionStorage.length) {
  localStorage.setItem('getSessionStorage', 'foobar');
  localStorage.removeItem('getSessionStorage', 'foobar');
};

Testowałem to na chrome, ff, safari czyli 11 czyli 10 ie9

Ta metoda „powinna działać w IE8”, ale nie mogłem jej przetestować, ponieważ moja IE ulegała awarii za każdym razem, gdy otwierałem kartę ... dowolna karta ... na dowolnej stronie internetowej. (dobry IE) PS: oczywiście musisz dołączyć podkładkę JSON, jeśli chcesz również obsługiwać IE8. :)

Podziękowania dla tego pełnego artykułu: http://blog.guya.net/2015/06/12/sharing-sessionstorage-between-tabs-for-secure-multi-tab-authentication/

nawlbergs
źródło
2
Jak niezawodne jest to rozwiązanie? Ponieważ jest oparty na wydarzeniach, czy jest szansa, że ​​przegapisz wydarzenie?
vivek241
2
Na podstawie odpowiedzi tutaj utworzyłem bibliotekę na localStorage i sessionStorage, aby to uprościć. Więc teraz po prostu wywołujesz storageManager.saveSyncedSessionData ('data', 'key'); lub storageManager.savePermanentData ('data', 'key'); itp. w zależności od potrzeb. Pełny kod jest tutaj: ebenmonney.com/blog/…
adentum
@ vivek241 Rozwiązanie działało świetnie, gdy rozmiar pliku JS był mniejszy, a "skrypt rozwiązania" podany powyżej jest ładowany jako pierwszy skrypt na stronie. Kiedy mój plik JS urósł zbytnio, powiedzmy 1000 lub więcej linii, nagle przestał działać i usunął również moje pliki cookie oraz określone dane localStorage. Nie jestem pewien, czy jest to niezawodne rozwiązanie dla różnych przeglądarek, na którym można polegać. Dlatego przepisano całą logikę, aby rozwiązać problem z samym plikiem cookie.
webblover
4
Czy zdarzenie nie zostanie wywołane we wszystkich wcześniej otwartych kartach?
Dtipson
3
Wygląda na BroadcastChannelto, że jest teraz dobrym narzędziem do tego. developers.google.com/web/updates/2016/09/broadcastchannel
alexbea
71

Używanie sessionStoragedo tego nie jest możliwe.

Z MDN Docs

Otwarcie strony w nowej karcie lub oknie spowoduje zainicjowanie nowej sesji.

Oznacza to, że nie możesz udostępniać plików między kartami, w tym celu powinieneś użyć localStorage

Henrik Andersson
źródło
8
OK, rozumiem, ale jak mogę wyczyścić localStorage, gdy wszystkie karty przeglądarki są zamknięte?
Vladimir Gordienko
Możesz zmienić plik cookie dokumentów, aby path='/'wymusić jego wyczyszczenie po zamknięciu okna przeglądarki. Ale jeśli chodzi o karty, nie mam teraz pojęcia.
Henrik Andersson
ok, przekopię się głębiej i dam znać, jeśli znalazłem rozwiązanie, pomyślmy na razie, co to niemożliwe))
Vladimir Gordienko
5
@Anmol tak, ale nie mogę już podać żadnego kodu, to było dawno temu. to brzydkie rozwiązanie, ale na mnie działa idealnie. Kluczem jest utrzymanie licznika otwartego tabulatora w pamięci lokalnej i zwiększanie go przy ładowaniu strony, ale zmniejszanie przy rozładowywaniu strony. Więc kiedy strona wyładuje się i tabsOpen == 1 to ostatnia karta i możemy wyczyścić wszystko. Musiałem się zająć pewnymi drobnymi sprawami, ale nie pamiętam, z czym dokładnie. Mam nadzieję, że to Ci pomoże!
Vladimir Gordienko
1
@VladimirGordienko co, jeśli zdarzenie unload, które usuwa localStoragedane, ma miejsce, ponieważ ktoś przechodzi do innej domeny, na tej samej karcie. Wydaje mi się, że to niepoprawnie usunie localStoragedane - karta nie została zamknięta, a jeśli dana osoba wróci, będzie chciała danych ponownie, prawda. Zresztą to ciekawe podejście, o tym nie pomyślałem: -)
KajMagnus
9
  1. Możesz po prostu użyć localStoragei zapamiętać datę, w której został utworzony session cookie. Kiedy localStorage„sesja” jest starsza niż wartość pliku cookie, możesz wyczyścićlocalStorage

    Wadą tego jest to, że ktoś może nadal odczytywać dane po zamknięciu przeglądarki, więc nie jest to dobre rozwiązanie, jeśli Twoje dane są prywatne i poufne.

  2. Możesz przechowywać swoje dane localStorageprzez kilka sekund i dodać nasłuchiwanie storagezdarzenia. W ten sposób dowiesz się, kiedy którakolwiek z zakładek zapisała coś w folderze localStoragei możesz skopiować jego zawartość do folderu sessionStorage, a następnie po prostu wyczyścićlocalStorage

Adassko
źródło
0

Moim rozwiązaniem, aby nie mieć sessionStorage przenoszonego przez karty, było utworzenie localProfile i odrzucenie tej zmiennej. Jeśli ta zmienna jest ustawiona, ale moje zmienne sessionStorage nie są gotowe i ponownie je zainicjuj. Gdy użytkownik wyloguje się, okno zamknie się, zniszcz tę zmienną localStorage

yardpenalty.com
źródło
-14

Oto rozwiązanie zapobiegające ścinaniu sesji między kartami przeglądarki w przypadku aplikacji Java. To zadziała dla IE (JSP / Servlet)

  1. Na pierwszej stronie JSP zdarzenie onload wywołuje aplet (wywołanie ajex), aby ustawić „window.title” i moduł śledzenia zdarzeń w sesji (tylko zmienna całkowita, która za pierwszym razem ma być ustawiona na 0)
  2. Upewnij się, że żadna z pozostałych stron nie ustawiła pliku window.title
  3. Wszystkie strony (w tym pierwsza strona) dodają skrypt java, aby sprawdzić tytuł okna po zakończeniu ładowania strony. jeśli tytuł nie zostanie znaleziony, zamknij bieżącą stronę / kartę (pamiętaj, aby cofnąć funkcję „window.unload” w takim przypadku)
  4. Ustaw page window.onunload zdarzenie skryptu java (dla wszystkich stron), aby przechwytywało zdarzenie odświeżania strony, jeśli strona została odświeżona, wywołaj serwlet, aby zresetować moduł śledzenia zdarzeń.

1) pierwsza strona JS

BODY onload="javascript:initPageLoad()"

function initPageLoad() {
    var xmlhttp;

    if (window.XMLHttpRequest) {
        // code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp = new XMLHttpRequest();
    } else {
        // code for IE6, IE5
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }

    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {                           var serverResponse = xmlhttp.responseText;
            top.document.title=serverResponse;
        }
    };
                xmlhttp.open("GET", 'data.do', true);
    xmlhttp.send();

}

2) wspólny JS dla wszystkich stron

window.onunload = function() {
    var xmlhttp;
    if (window.XMLHttpRequest) {
        // code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp = new XMLHttpRequest();
    } else {
        // code for IE6, IE5
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {             
            var serverResponse = xmlhttp.responseText;              
        }
    };

    xmlhttp.open("GET", 'data.do?reset=true', true);
    xmlhttp.send();
}

var readyStateCheckInterval = setInterval(function() {
if (document.readyState === "complete") {
    init();
    clearInterval(readyStateCheckInterval);
}}, 10);
function init(){ 
  if(document.title==""){   
  window.onunload=function() {};
  window.open('', '_self', ''); window.close();
  }
 }

3) web.xml - mapowanie serwletów

<servlet-mapping>
<servlet-name>myAction</servlet-name>
<url-pattern>/data.do</url-pattern>     
</servlet-mapping>  
<servlet>
<servlet-name>myAction</servlet-name>
<servlet-class>xx.xxx.MyAction</servlet-class>
</servlet>

4) kod serwletu

public class MyAction extends HttpServlet {
 public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws IOException {
    Integer sessionCount = (Integer) request.getSession().getAttribute(
            "sessionCount");
    PrintWriter out = response.getWriter();
    Boolean reset = Boolean.valueOf(request.getParameter("reset"));
    if (reset)
        sessionCount = new Integer(0);
    else {
        if (sessionCount == null || sessionCount == 0) {
            out.println("hello Title");
            sessionCount = new Integer(0);
        }
                          sessionCount++;
    }
    request.getSession().setAttribute("sessionCount", sessionCount);
    // Set standard HTTP/1.1 no-cache headers.
    response.setHeader("Cache-Control", "private, no-store, no-cache, must-                      revalidate");
    // Set standard HTTP/1.0 no-cache header.
    response.setHeader("Pragma", "no-cache");
} 
  }
DTB
źródło
3
To pytanie dotyczy javascript, nie ma nic wspólnego z javascript.
victorpacheco3107
To jest pytanie bardziej o sessionStorage i
localStorage