utiliser localStorage sur les sous-domaines

95

Je remplace les cookies par localStorage sur les navigateurs qui peuvent le prendre en charge (n'importe qui sauf IE). Le problème vient de site.com et www . site.com stocke ses propres objets localStorage séparés. Je crois que www est considéré comme un sous-domaine (une décision stupide si vous me demandez). Si un utilisateur était à l'origine sur site.com et décide de taper www . site.com lors de sa prochaine visite, toutes ses données personnelles seront inaccessibles. Comment faire pour que tous mes "sous-domaines" partagent le même localStorage que le domaine principal?

JoJo
la source
4
Firefox et IE8 prennent en charge le stockage des données persistantes sous un domaine spécifié par l'utilisateur. Par exemple sur FF, vous pouvez faire globalStorage ['site.com'] et cela sera accessible à www.site.com et site.com. Je n'ai toujours pas compris comment faire cela dans la mise en œuvre de Chrome.
JoJo du
9
Pensez à utiliser l'un ou l'autre - redirigez tous les utilisateurs visitant le site www. sous-domaine au domaine sans sous-domaine, ou inversement.
Elad Nava
J'ai créé un article il y a longtemps: Cross-Domain LocalStorage
jcubic

Réponses:

94

C'est ainsi que je l'utilise dans plusieurs domaines ...

  • Utilisez un iframe de votre domaine parent - disons parent.com
  • Ensuite, sur chaque domaine child.com, faites simplement un postMessage à votre iframe parent.com
  • Tout ce que vous avez à faire est de configurer un protocole d'interprétation de vos messages postMessage pour parler à l'iframe parent.com.

J'espère que cela aide :)

Mayank Jain
la source
2
C'est la vraie réponse, pas celle cochée. Je l'ai fait moi-même, mais j'ai également créé un wrapper de rappel pratique avec postMessage.
Jason Sebring
4
Voici un bon article avec un exemple de code expliquant cette méthode: jcubic.wordpress.com/2014/06/20/cross-domain-localstorage
Todd Price
4
Notez que cela n'est possible que lorsque les cookies tiers ne sont pas désactivés: stackoverflow.com/a/44097269/4311428
Max
6
Apple a mis à jour les valeurs par défaut sur Safari 7+ à la fois sur ordinateur et sur mobile pour bloquer les données tierces. L'option est maintenant appelée "Bloquer les cookies et autres données du site Web" qui fait référence à des choses comme le stockage local qui sont maintenant complètement isolés par domaine. Cette méthode ne fonctionnera pas dans Safari
Aranganathan
2
@Max @Aranganathan cela fonctionne toujours pour le cas de question d'origine - site.com/ www.site.comtant que les sous-domaines sont sur le même domaine parent
Kostiantyn
40

Si vous utilisez la solution iframe et postMessage uniquement pour ce problème particulier, je pense qu'il pourrait être moins de travail (à la fois au niveau du code et du calcul) de simplement stocker les données dans un cookie sans sous-domaine et, si ce n'est déjà fait dans localStorage lors du chargement, récupérez-le dans le cookie .

Avantages:

  • N'a pas besoin de la configuration supplémentaire d'iframe et de postMessage.

Les inconvénients:

  • Rendra les données disponibles sur tous les sous-domaines (pas seulement www), donc si vous ne faites pas confiance à tous les sous-domaines, cela peut ne pas fonctionner pour vous.
  • Enverra les données au serveur à chaque demande. Pas génial, mais selon votre scénario, peut-être encore moins de travail que la solution iframe / postMessage.
  • Si vous faites cela, pourquoi ne pas simplement utiliser les cookies directement? Cela dépend de votre contexte.
  • Taille maximale des cookies 4K, totale pour tous les cookies du domaine (merci à Blake de l'avoir signalé dans les commentaires)

Je suis cependant d'accord avec les autres commentateurs, cela semble être une option spécifiable pour localStorage, donc des solutions de rechange ne sont pas nécessaires.

Mat
la source
29
Contre: Taille maximale du cookie de 4k
Blake Miller
17
De plus, comme je l'ai appris à la dure, la limite de 4k correspond à la somme des tailles de tous les cookies pour un seul domaine, pas pour chaque cookie.
Blake Miller
autres inconvénients: - les cookies seront probablement bloqués par des bloqueurs de publicités - les cookies sont destinés à être utilisés pour partager de petites données entre le serveur et le client, si le serveur n'utilise pas les données que vous stockez dans le cookie, il s'agit par conséquent d'une mauvaise utilisation
Enno
32

Je suggère de faire rediriger site.com vers www.site.com à la fois pour la cohérence et pour éviter des problèmes comme celui-ci.

Envisagez également d'utiliser une solution multi-navigateurs telle que PersistJS qui peut utiliser le stockage natif de chaque navigateur.

Eran Galperin
la source
Je n'ai pas d'accès administrateur aux serveurs pour effectuer une telle redirection. Cette bibliothèque me permet-elle de partager des données persistantes entre www et non-www? Après quelques lectures, il semble que presque tous les mécanismes de stockage des navigateurs ne le permettent pas. Peu importe s'il s'agit de cookies ou de stockage local, nous allons rencontrer ce problème ...
JoJo
Oui, le stockage dépend normalement du domaine, y compris le sous-domaine. C'est pourquoi j'ai suggéré une redirection. Vous n'avez pas nécessairement besoin d'un accès administrateur, utilisez simplement une règle .htaccess dans la racine du document
Eran Galperin
1
@JoJo Il existe plusieurs façons de rediriger, par exemple en envoyant l'en-tête Location, ou via une <meta>balise HTML, ou même via JS window.location.
Sony Santos le
1
Ceci évite simplement la réponse. Voir la réponse de Mayank comme correcte.
Jason Sebring
1
+1 @avoiding, en plus cela n'a pas d'importance pour les autres cas - comme celui pour lequel je suis ici lang1.domain.com - lang2.domain.com
r --------- k
6

Définir comme cookie dans le domaine principal -

document.cookie = "key=value;domain=.mydomain.com"

puis prenez les données de n'importe quel domaine principal ou sous-domaine et définissez-le sur le localStorage

URL87
la source
1

ce type de solution pose de nombreux problèmes comme celui-ci. pour des raisons de cohérence et de référencement, la redirection sur le domaine principal est la meilleure solution.

faire la redirection au niveau du serveur

Comment rediriger www vers non-www avec Nginx

https://www.digitalocean.com/community/tutorials/how-to-redirect-www-to-non-www-with-nginx-on-centos-7

ou tout autre niveau comme la route 53 si vous utilisez

Jamil Noyda
la source
1

C'est ainsi:

Pour le partage entre les sous-domaines d'un superdomaine donné (par exemple, example.com), il existe une technique que vous pouvez utiliser dans cette situation. Il peut être appliqué à localStorage, IndexedDB, SharedWorker, BroadcastChannel, etc., qui offrent tous des fonctionnalités partagées entre les pages de même origine, mais pour une raison quelconque ne respectent aucune modification document.domainqui permettrait de les utiliser le superdomaine leur origine directement.

(1) Choisissez un domaine "principal" auquel les données doivent appartenir: c'est-à-dire que https://example.com ou https://www.example.com contiendra vos données de stockage local. Disons que vous choisissez https://example.com .

(2) Utilisez localStorage normalement pour les pages de ce domaine choisi.

(3) Sur toutes les pages https://www.example.com (l' autre domaine), utilisez javascript pour définir document.domain = "example.com";. Créez ensuite également caché <iframe>, et de naviguer à une page sur le choix https://example.com domaine ( Peu importe ce que la page , aussi longtemps que vous pouvez insérer un très petit extrait de javascript là - bas. Si vous lors de la création du site, créez simplement une page vide spécialement à cet effet. Si vous écrivez une extension ou un script utilisateur de style Greasemonkey et que vous n'avez donc aucun contrôle sur les pages de example.comserveur, choisissez simplement la page la plus légère que vous puissiez trouver et insérez-y votre script. Une sorte de page "non trouvée" conviendrait probablement).

(4) Le script de la page iframe masquée n'a besoin que de (a) défini document.domain = "example.com";et (b) d'avertir la fenêtre parente lorsque cela est fait. Après cela, la fenêtre parente peut accéder à la fenêtre iframe et à tous ses objets sans restriction! Ainsi, la page iframe minimale est quelque chose comme:

<!doctype html>
<html>
<head>
  <script>
    document.domain = "example.com";
    window.parent.iframeReady();  // function defined & called on parent window
  </script>
</head>
<body></body>
</html>

Si vous écrivez un script utilisateur, vous ne voudrez peut-être pas ajouter des fonctions accessibles de l'extérieur, telles que iframeReady()votre unsafeWindow, donc un meilleur moyen de notifier le script utilisateur de la fenêtre principale peut être d'utiliser un événement personnalisé:

    window.parent.dispatchEvent(new CustomEvent("iframeReady"));

Ce que vous détecteriez en ajoutant un écouteur pour l'événement "iframeReady" personnalisé à la fenêtre de votre page principale.

(REMARQUE: vous devez définir document.domain = "example.com" même si le domaine de l'iframe est déjà example.com : l'attribution d'une valeur à document.domain définit implicitement le port de l'origine sur null, et les deux ports doivent correspondre pour l'iframe et son parent doit être considéré comme ayant la même origine. Voir la note ici: https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#Changing_origin )

(5) Une fois que le caché iframe a informé sa fenêtre parent qu'il est prêt, le script dans la fenêtre parent peut simplement utiliser iframe.contentWindow.localStorage, iframe.contentWindow.indexedDB, iframe.contentWindow.BroadcastChannel, au iframe.contentWindow.SharedWorkerlieu de window.localStorage, window.indexedDB, etc ... et tous ces objets seront étendus à l'élu https: // example.com origin - ils auront donc la même origine partagée pour toutes vos pages!

La partie la plus délicate de cette technique est que vous devez attendre que l'iframe se charge avant de continuer. Vous ne pouvez donc pas simplement commencer à utiliser localStorage dans votre gestionnaire DOMContentLoaded, par exemple. Vous pouvez également ajouter une gestion des erreurs pour détecter si l'iframe masqué ne se charge pas correctement.

De toute évidence, vous devez également vous assurer que l'iframe caché n'est pas supprimé ou parcouru pendant la durée de vie de votre page ... OTOH Je ne sais pas quel en serait le résultat, mais très probablement de mauvaises choses se produiraient.

Et, une mise en garde: le réglage / la modification document.domainpeut être bloqué à l'aide de l'en- Feature-Policytête, auquel cas cette technique ne sera pas utilisable comme décrit.


Cependant, il existe une généralisation beaucoup plus compliquée de cette technique, qui ne peut pas être bloquée par Feature-Policy, et qui permet également à des domaines totalement indépendants de partager des données, des communications et des travailleurs partagés (c'est-à-dire pas seulement des sous-domaines d'un super-domaine commun). @Mayank Jain l'a déjà décrit dans sa réponse, à savoir:

L'idée générale est que, tout comme ci-dessus, vous créez une iframe cachée pour fournir l'origine correcte pour l'accès; mais au lieu de simplement saisir directement les propriétés de la fenêtre iframe, vous utilisez un script à l'intérieur de l'iframe pour faire tout le travail, et vous communiquez entre l'iframe et votre fenêtre principale uniquement en utilisant postMessage()et addEventListener("message",...).

Cela fonctionne car postMessage()peut être utilisé même entre des fenêtres d'origine différente. Mais c'est aussi beaucoup plus compliqué car vous devez tout faire passer par une sorte d'infrastructure de messagerie que vous créez entre l'iframe et la fenêtre principale, plutôt que d'utiliser simplement les API localStorage, IndexedDB, etc. directement dans le code de votre fenêtre principale.

Faire
la source
0

C'est ainsi que je l'ai résolu pour mon site Web. J'ai redirigé toutes les pages sans www vers www.site.com. De cette façon, il faudra toujours le stockage local de www.site.com

Ajoutez ce qui suit à votre .htacess , (créez-en un si vous ne l'avez pas déjà) dans le répertoire racine

RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
Ayush Baheti
la source
5
Je suis très tenté de voter contre cela, mais je ne le ferai pas car cela peut aider le cas d'utilisation de l'OP, mais pour les personnes qui souhaitent garder des sessions sur myapp.com et developer.myapp.com et support.myapp.com, cette réponse est pas bon.
Don Omondi
hey @DonOmondi j'apprécierais si vous pouvez m'aider avec les liens pour ce que vous suggérez!
Ayush Baheti
3
L'OP a demandé "utiliser localStorage sur les sous-domaines", votre réponse est "rediriger www vers non-www" des choses très différentes mais cela peut fonctionner si et seulement si le sous-domaine spécifique est "www.abc.com" pour les cas généraux, d'autres réponses sont ici plus pratique.
Don Omondi