session du navigateur Stockage. partager entre les onglets?

151

J'ai des valeurs sur mon site que je souhaite effacer lorsque le navigateur est fermé. J'ai choisi sessionStoragede stocker ces valeurs. Lorsque l'onglet est fermé, ils sont effectivement effacés et conservés si l'utilisateur appuie sur f5; Mais si l'utilisateur ouvre un lien dans un onglet différent, ces valeurs ne sont pas disponibles.

Comment puis-je partager des sessionStoragevaleurs entre tous les onglets du navigateur avec mon application?

Le cas d'utilisation: mettez une valeur dans un espace de stockage, gardez cette valeur accessible dans tous les onglets du navigateur et effacez-la si tous les onglets sont fermés.

if (!sessionStorage.getItem(key)) {
    sessionStorage.setItem(key, defaultValue)
}
Vladimir Gordienko
la source
9
C'est bizarre pour moi que cela ait été fermé en double. Nomination pour la réouverture. L'autre sujet concerne «comment communiquer entre plusieurs onglets», qui sonne différemment, et est également différent, lorsque je commence à lire cet autre sujet.
KajMagnus
Est-il possible d'utiliser des cookies? qui se comportent comme ça par défaut? (mais en effet - pour obtenir et définir l'action, ils
exigeront

Réponses:

133

Vous pouvez utiliser localStorage et son eventListener "stockage" pour transférer les données sessionStorage d'un onglet à un autre.

Ce code devrait exister sur TOUS les onglets. Il devrait s'exécuter avant vos autres scripts.

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

J'ai testé ça en chrome, ff, safari, ie 11, ie 10, ie9

Cette méthode "devrait fonctionner dans IE8" mais je n'ai pas pu la tester car mon IE plantait chaque fois que j'ouvrais un onglet .... n'importe quel onglet ... sur n'importe quel site Web. (bon ol IE) PS: vous devrez évidemment inclure un shim JSON si vous voulez aussi le support IE8. :)

Le crédit va à cet article complet: http://blog.guya.net/2015/06/12/sharing-sessionstorage-between-tabs-for-secure-multi-tab-authentication/

nawlbergs
la source
2
Quelle est la fiabilité de cette solution? Puisqu'il est basé sur un événement, y a-t-il une chance de manquer un événement?
vivek241
2
Sur la base des réponses ici, j'ai créé une bibliothèque sur localStorage et sessionStorage pour simplifier cela. Alors maintenant, vous appelez simplement storageManager.saveSyncedSessionData ('data', 'key'); ou storageManager.savePermanentData ('data', 'key') ;, etc. en fonction de ce dont vous avez besoin. Le code complet est ici: ebenmonney.com/blog/…
adentum
@ vivek241 La solution fonctionnait très bien pour moi lorsque la taille du fichier JS était plus petite et que "le script de solution" donné ci-dessus est chargé comme premier script de la page. Lorsque mon fichier JS est devenu trop volumineux, disons 1000 lignes ou plus, il a soudainement cessé de fonctionner et a également supprimé mes cookies et mes données spécifiques de stockage local. Je ne suis pas sûr qu'il s'agisse d'une solution fiable ou multi-navigateurs sur laquelle on pourrait compter. Alors, réécrivez toute la logique pour résoudre le problème avec le cookie seul.
webblover
4
L'événement ne serait-il pas déclenché dans tous les onglets précédemment ouverts?
Dtipson
3
Il semble que BroadcastChannelc'est maintenant un bon outil pour faire cela. développeurs.google.com
web
71

L'utilisation sessionStoragepour cela n'est pas possible.

À partir des documents MDN

L'ouverture d'une page dans un nouvel onglet ou une nouvelle fenêtre entraînera le lancement d'une nouvelle session.

Cela signifie que vous ne pouvez pas partager entre les onglets, pour cela, vous devez utiliser localStorage

Henrik Andersson
la source
8
Ok, je l'ai, mais comment puis-je effacer localStorage lorsque tous les onglets du navigateur sont fermés?
Vladimir Gordienko
Vous pouvez modifier le cookie des documents pour le path='/'forcer ainsi à s'effacer lorsque la fenêtre du navigateur est fermée. Mais pour les onglets, je n'en ai aucune idée pour le moment.
Henrik Andersson
ok je vais creuser plus profondément et vous faire savoir si j'ai trouvé une solution, pensons pour l'instant à ce qu'il est impossible))
Vladimir Gordienko
5
@Anmol oui, mais je ne peux pas fournir de code déjà, c'était il y a loin. c'est une solution moche mais cela fonctionne parfaitement pour moi. La clé ici est de garder le compteur tabsOpen dans le stockage local et de l'augmenter au chargement de la page mais de le diminuer au déchargement de la page. Ainsi, lorsque la page est déchargée et tabsOpen == 1 son dernier onglet et nous pouvons effacer tout. Il y avait quelques petites choses que je devais gérer mais je ne me souviens pas quoi exactement. J'espère que cela vous aidera!
Vladimir Gordienko
1
@VladimirGordienko et si l'événement de déchargement qui supprime les localStoragedonnées se produit parce que quelqu'un accède à un domaine différent, dans le même onglet. Il me semble que cela supprimera incorrectement les localStoragedonnées - l'onglet ne s'est pas fermé, et si la personne revient en arrière, elle voudrait à nouveau les données, à droite. Quoi qu'il en soit, c'est une approche intéressante, je n'y ai pas pensé: -)
KajMagnus
9
  1. Vous pouvez simplement utiliser localStorageet vous souvenir de la date à laquelle il a été créé pour la première fois session cookie. Lorsque localStorage"session" est plus ancienne que la valeur du cookie, vous pouvez effacer lelocalStorage

    L'inconvénient est que quelqu'un peut toujours lire les données après la fermeture du navigateur, ce n'est donc pas une bonne solution si vos données sont privées et confidentielles.

  2. Vous pouvez stocker vos données localStoragependant quelques secondes et ajouter un écouteur d'événement pour un storageévénement. De cette façon, vous saurez quand l'un des onglets a écrit quelque chose dans le localStorageet vous pouvez copier son contenu dans le sessionStorage, puis effacez simplement lelocalStorage

Adassko
la source
0

Ma solution pour ne pas avoir sessionStorage transférable sur les onglets était de créer un profil local et de supprimer cette variable. Si cette variable est définie mais que mes variables sessionStorage ne sont pas disponibles, réinitialisez-les. Lorsque l'utilisateur se déconnecte, la fenêtre se ferme, détruit cette variable localStorage

yardpenalty.com
la source
-14

Voici une solution pour éviter le cisaillement de session entre les onglets du navigateur pour une application java. Cela fonctionnera pour IE (JSP / Servlet)

  1. Dans votre première page JSP, l'événement onload appelle un servlet (appel ajex) pour configurer un "window.title" et un suivi d'événements dans la session (juste une variable entière à définir comme 0 pour la première fois)
  2. Assurez-vous qu'aucune des autres pages ne définit de fenêtre.
  3. Toutes les pages (y compris la première page) ajoutent un script java pour vérifier le titre de la fenêtre une fois le chargement de la page terminé. si le titre n'est pas trouvé, fermez la page / l'onglet en cours (assurez-vous d'annuler la fonction "window.unload" lorsque cela se produit)
  4. Définissez l'événement de script java page window.onunload (pour toutes les pages) pour capturer l'événement d'actualisation de la page, si une page a été actualisée, appelez le servlet pour réinitialiser le suivi des événements.

1) première page 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 commun pour toutes les pages

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 - mappage de 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) code de 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");
} 
  }
DTB
la source
3
Cette question concerne javascript, elle n'a rien à voir avec javascript.
victorpacheco3107
Cette question est plus sur sessionStorage et localStorage
RR1112