sessione del browser condividere tra le schede?


151

Ho alcuni valori nel mio sito che desidero cancellare alla chiusura del browser. Ho scelto sessionStoragedi memorizzare quei valori. Quando la tab è chiusa, vengono effettivamente cancellati e mantenuti se l'utente preme f5; Ma se l'utente apre un collegamento in un'altra scheda, questi valori non sono disponibili.

Come posso condividere sessionStoragevalori con tutte le schede del browser con la mia applicazione?

Il caso d'uso: inserisci un valore in un certo spazio di archiviazione, mantieni quel valore accessibile in tutte le schede del browser e cancellalo se tutte le schede sono chiuse.

if (!sessionStorage.getItem(key)) {
    sessionStorage.setItem(key, defaultValue)
}

9
È strano per me che questo sia stato chiuso come duplicato. Nomina per la riapertura. L'altro argomento riguarda "come comunicare tra più schede", che suona diverso, ed è anche diverso, quando inizio a leggere quell'altro argomento.
KajMagnus,

È possibile utilizzare i cookie? che si comportano così per impostazione predefinita? (ma in effetti - per ottenere e impostare l'azione richiederanno un'ulteriore implementazione) developer.mozilla.org/en-US/docs/Web/API/Document/cookie
lingar

Risposte:


133

È possibile utilizzare localStorage e il suo "storage" eventListener per trasferire i dati di sessionStorage da una scheda all'altra.

Questo codice dovrebbe esistere in TUTTE le schede. Dovrebbe essere eseguito prima degli altri script.

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

Ho provato questo in Chrome, FF, Safari, cioè 11, cioè 10, ie9

Questo metodo "dovrebbe funzionare in IE8" ma non sono riuscito a testarlo poiché il mio IE si arrestava in modo anomalo ogni volta che aprivo una scheda ... qualsiasi scheda ... su qualsiasi sito Web. (buon vecchio IE) PS: ovviamente dovrai includere uno shim JSON se vuoi anche il supporto IE8. :)

Il merito va a questo articolo completo: http://blog.guya.net/2015/06/12/sharing-sessionstorage-between-tabs-for-secure-multi-tab-authentication/


2
Quanto è affidabile questa soluzione? Dal momento che è basato su eventi, c'è qualche possibilità di perdere un evento?
vivek241,

2
Sulla base delle risposte qui ho creato una libreria su localStorage e sessionStorage per semplificare ciò. Quindi ora basta chiamare storageManager.saveSyncedSessionData ('data', 'chiave'); oppure storageManager.savePermanentData ('data', 'chiave') ;, ecc. in base a ciò di cui hai bisogno. Il codice completo è qui: ebenmonney.com/blog/…
adentum il

@ vivek241 La soluzione ha funzionato perfettamente per me quando le dimensioni del file JS erano inferiori e "lo script della soluzione" sopra indicato viene caricato come primo script nella pagina. Quando il mio file JS è diventato troppo grande, diciamo 1000 o più righe, ha smesso improvvisamente di funzionare e ha rimosso anche i miei cookie e i dati specifici di LocalStorage. Non sono sicuro che si tratti di una soluzione affidabile o cross-browser su cui fare affidamento. Quindi, riscrivi tutta la logica per risolvere il problema con il solo cookie.
webblover il

4
L'evento non verrebbe attivato in tutte le schede precedentemente aperte?
Dtipson,

3
Sembra che BroadcastChannelora sia un buon strumento per farlo. developers.google.com/web/updates/2016/09/broadcastchannel
alexbea

71

utilizzando sessionStorage per questo non è possibile.

Dai documenti MDN

L'apertura di una pagina in una nuova scheda o finestra comporterà l'avvio di una nuova sessione.

Ciò significa che non è possibile condividere tra le schede, per questo è necessario utilizzare localStorage


8
Ok, ho capito, ma come posso cancellare localStorage quando tutte le schede del browser sono chiuse?
Vladimir Gordienko,

È possibile modificare il cookie dei documenti in path='/'modo da costringerlo a cancellare quando la finestra del browser è chiusa. Ma per le schede, non ho idea in questo momento.
Henrik Andersson,

ok approfondirò e ti farò sapere se ho trovato una soluzione, per ora pensa a cosa sia impossibile))
Vladimir Gordienko

5
@Anmol sì, ma non posso già fornire alcun codice, era molto tempo fa. questa è una brutta soluzione ma funziona perfettamente per me. La chiave è quella di mantenere le schede Contatore aperto nella memoria locale e aumentarlo al caricamento della pagina ma diminuire allo scarico della pagina. Quindi quando la pagina viene scaricata e le schede si aprono == 1 la sua ultima scheda e possiamo cancellare tutto. C'erano alcune cose minori che dovevo gestire ma non ricordo esattamente cosa. Spero che ti possa aiutare!
Vladimir Gordienko,

1
@VladimirGordienko cosa succede se l'evento di scaricamento che elimina i localStoragedati accade perché qualcuno naviga in un dominio diverso, nella stessa scheda. Mi sembra che questo cancellerà erroneamente i localStoragedati - la scheda non si è chiusa e se la persona torna indietro, vorrebbe di nuovo i dati, giusto. Ad ogni modo, è un approccio interessante, non ci ho pensato: -)
KajMagnus,

9
  1. Puoi semplicemente usare localStoragee ricordare la data in cui è stata creata per la prima volta session cookie. quandolocalStorage "sessione" è più vecchia del valore del cookie, è possibile cancellare illocalStorage

    Contro questo è che qualcuno può ancora leggere i dati dopo la chiusura del browser, quindi non è una buona soluzione se i tuoi dati sono privati ​​e riservati.

  2. Puoi archiviare i tuoi dati localStorageper un paio di secondi e aggiungere un listener di eventi per un storageevento. In questo modo saprai quando una delle schede ha scritto qualcosa su localStoragee puoi copiarne il contenuto su sessionStorage, quindi cancellare illocalStorage



0

La mia soluzione per non avere sessionStorage trasferibile su schede era creare un LocalProfile e cancellare questa variabile. Se questa variabile è impostata ma le mie variabili sessionStorage non sono ancora attive, reinizializzarle. Quando l'utente si disconnette la finestra si chiude distruggere questa variabile localStorage


-14

Ecco una soluzione per impedire il troncamento della sessione tra le schede del browser per un'applicazione java. Questo funzionerà per IE (JSP / Servlet)

  1. Nella tua prima pagina JSP, l'evento onload chiama un servlet (chiamata ajex) per impostare un "window.title" e un tracker eventi nella sessione (solo una variabile intera da impostare come 0 per la prima volta)
  2. Assicurati che nessuna delle altre pagine imposti un window.title
  3. Tutte le pagine (inclusa la prima pagina) aggiungono uno script java per controllare il titolo della finestra una volta completato il caricamento della pagina. se il titolo non viene trovato, chiudere la pagina / scheda corrente (assicurarsi di annullare la funzione "window.unload" quando ciò si verifica)
  4. Imposta pagina window.onunload evento script java (per tutte le pagine) per acquisire l'evento di aggiornamento della pagina, se una pagina è stata aggiornata chiama il servlet per ripristinare il tracker eventi.

1) prima pagina 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) JS comune per tutte le pagine

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 - mappatura servlet

<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) codice servlet

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

3
Questa domanda riguarda javascript, non ha nulla a che fare con javascript.
victorpacheco3107,

Questa è una domanda più su sessionStorage e localStorage
RR1112
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.