usar localStorage en todos los subdominios


95

Estoy reemplazando las cookies con localStorage en los navegadores que pueden admitirlo (cualquiera menos IE). El problema es site.com y www . site.com almacena sus propios objetos localStorage separados. Creo que www se considera un subdominio (una decisión estúpida si me preguntas). Si un usuario estaba originalmente en site.com y decide escribir www . site.com en su próxima visita, todos sus datos personales serán inaccesibles. ¿Cómo hago para que todos mis "subdominios" compartan el mismo localStorage que el dominio principal?


4
Firefox e IE8 admiten el almacenamiento de datos persistentes en un dominio especificado por el usuario. Por ejemplo, en FF, puede hacer globalStorage ['site.com'] y esto será posible en www.site.com y site.com. Todavía no he descubierto cómo hacer esto en la implementación de Chrome.
JoJo

9
Considere usar uno o el último: redirija a todos los usuarios que visitan con www. subdominio al dominio sin subdominio, o al revés.
Elad Nava

Respuestas:


94

Así es como lo uso en todos los dominios ...

  • Utilice un iframe de su dominio principal, por ejemplo, parent.com
  • Luego, en cada dominio child.com, simplemente envíe un mensaje posterior a su iframe parent.com
  • Todo lo que necesita hacer es configurar un protocolo de cómo interpretar sus mensajes postMessage para hablar con el iframe parent.com.

Espero que ayude :)


2
Esta es la respuesta real, no la marcada. Lo hice yo mismo, pero también creé un contenedor de devolución de llamada conveniente con postMessage.
Jason Sebring

4
Aquí hay un buen artículo con un código de ejemplo que explica este método: jcubic.wordpress.com/2014/06/20/cross-domain-localstorage
Todd Price

4
Tenga en cuenta que esto solo es posible cuando las cookies de terceros no están deshabilitadas: stackoverflow.com/a/44097269/4311428
Max

6
Apple ha actualizado los valores predeterminados en Safari 7+ tanto en computadoras de escritorio como en dispositivos móviles para bloquear los datos de terceros. La opción ahora se llama "Bloquear cookies y otros datos de sitios web", que se refiere a cosas como almacenamiento local que ahora están completamente aislados por dominio. Este método no funcionará en Safari
Aranganathan

2
@Max @Aranganathan todavía funciona para el caso de pregunta original - site.com/ www.site.comsiempre que los subdominios estén en el mismo dominio principal
Kostiantyn

41

Si está utilizando la solución iframe y postMessage solo para este problema en particular, creo que podría ser menos trabajo (tanto en código como en cálculo) simplemente almacenar los datos en una cookie sin subdominio y, si aún no lo está en localStorage on load, cójalo de la cookie .

Pros:

  • No necesita la configuración adicional de iframe y postMessage.

Contras:

  • Hará que los datos estén disponibles en todos los subdominios (no solo en www), por lo que si no confía en todos los subdominios, es posible que no funcione para usted.
  • Enviará los datos al servidor en cada solicitud. No es genial, pero dependiendo de su escenario, tal vez aún menos trabajo que la solución iframe / postMessage.
  • Si está haciendo esto, ¿por qué no usar las cookies directamente? Depende de tu contexto.
  • Tamaño máximo de cookie de 4K, total en todas las cookies del dominio (gracias a Blake por señalar esto en los comentarios)

Sin embargo, estoy de acuerdo con otros comentaristas, esto parece que debería ser una opción especificable para localStorage, por lo que no se requieren soluciones alternativas.


29
Con: tamaño máximo de cookie de 4k
Blake Miller

17
Además, como aprendí de la manera difícil, el límite de 4k es para la suma de los tamaños de todas las cookies para un solo dominio, no para cada cookie.
Blake Miller

otras desventajas: - es más probable que los bloqueadores de anuncios bloqueen las cookies - las cookies están diseñadas para compartir pequeños datos entre el servidor y el cliente, si el servidor no está usando los datos que usted almacena en la cookie, esto es, en consecuencia, un mal uso
Enno

32

Sugiero hacer que site.com redireccione a www.site.com tanto por coherencia como para evitar problemas como este.

Además, considere usar una solución de navegador cruzado como PersistJS que puede usar el almacenamiento nativo de cada navegador.


No tengo acceso de administrador a los servidores para realizar dicha redirección. ¿Esa biblioteca me permite compartir datos persistentes entre www y no www? Después de leer un poco, parece que casi todos los mecanismos de almacenamiento de los navegadores no lo permiten. No importa si son cookies o localStorage, vamos a encontrarnos con este problema ...
JoJo

Sí, el almacenamiento normalmente depende del dominio, incluido el subdominio. Por eso sugerí una redirección. No necesita necesariamente acceso de administrador, solo use una regla .htaccess en la raíz del documento
Eran Galperin

1
@JoJo Hay varias formas de redireccionar, por ejemplo, enviando el encabezado Location, o mediante una <meta>etiqueta HTML, o incluso mediante JS window.location.
Sony Santos

1
Esto es simplemente evitar la respuesta. Vea la respuesta de Mayank como correcta.
Jason Sebring

1
+1 @avoiding, además, esto es irrelevante para otros casos, como el que estoy aquí lang1.domain.com - lang2.domain.com
r --------- k

6

Establecer como cookie en el dominio principal -

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

y luego tomar los datos de cualquier dominio principal o subdominio y configurarlos en el localStorage




1

Así es como:

Para compartir entre subdominios de un superdominio determinado (por ejemplo, example.com), existe una técnica que puede utilizar en esa situación. Se puede aplicar a localStorage, IndexedDB, SharedWorker, BroadcastChannel, etc, todos los cuales ofrecen funcionalidad compartida entre las páginas del mismo origen, pero por alguna razón no respetan ninguna modificación a document.domainque ejerzan el superdomain como su origen directamente.

(1) Elija un dominio "principal" para que pertenezcan los datos: es decir, https://example.com o https://www.example.com mantendrán sus datos de almacenamiento local. Digamos que elige https://example.com .

(2) Utilice localStorage normalmente para las páginas de ese dominio elegido.

(3) En todas las páginas https://www.example.com (el otro dominio), use javascript para configurar document.domain = "example.com";. Luego, cree también un oculto <iframe>y navegue a alguna página en el dominio https://example.com elegido ( no importa qué página , siempre que pueda insertar un pequeño fragmento de JavaScript allí. Si ' Al crear el sitio, simplemente cree una página vacía específicamente para este propósito. Si está escribiendo una extensión o un script de usuario al estilo Greasemonkey y, por lo tanto, no tiene ningún control sobre las páginas de example.comservidor, simplemente elija la página más liviana que pueda encontrar e inserte su script en ella. Algún tipo de página "no encontrada" probablemente estaría bien).

(4) La secuencia de comandos en la página de iframe oculta solo necesita (a) configurarse document.domain = "example.com";y (b) notificar a la ventana principal cuando esto esté hecho. Después de eso, la ventana principal puede acceder a la ventana iframe y a todos sus objetos sin restricciones. Entonces, la página de iframe mínima es algo como:

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

Si escribir un userscript, puede que no desee añadir funciones accesibles externamente como iframeReady()a su unsafeWindow, por lo que en lugar de una mejor forma de notificar a la ventana principal userscript podría ser el uso de un evento personalizado:

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

Lo cual detectaría agregando un oyente para el evento personalizado "iframeReady" en la ventana de su página principal.

(NOTA: Debe establecer document.domain = "example.com" incluso si el dominio del iframe ya es example.com : la asignación de un valor a document.domain establece implícitamente el puerto de origen en nulo, y ambos puertos deben coincidir con el iframe y su padre se considera del mismo origen. Consulte la nota aquí: https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#Changing_origin )

(5) Una vez que el iframe oculto haya informado a su ventana primaria que está listo, la escritura en la ventana padre solo puede usar iframe.contentWindow.localStorage, iframe.contentWindow.indexedDB, iframe.contentWindow.BroadcastChannel, iframe.contentWindow.SharedWorkeren lugar de window.localStorage, window.indexedDB, etc ... y todos estos objetos serán ámbito es el elegido https: // origen de example.com - ¡así tendrán el mismo origen compartido para todas sus páginas!

La parte más incómoda de esta técnica es que debe esperar a que se cargue el iframe antes de continuar. Entonces, no puede simplemente comenzar a usar alegremente localStorage en su controlador DOMContentLoaded, por ejemplo. También es posible que desee agregar algún manejo de errores para detectar si el iframe oculto no se carga correctamente.

Obviamente, también debe asegurarse de que el iframe oculto no se elimine ni se navegue durante la vida útil de su página ... OTOH No sé cuál sería el resultado de eso, pero es muy probable que sucedan cosas malas.

Y una advertencia: la configuración / cambio document.domainse puede bloquear mediante el Feature-Policyencabezado, en cuyo caso esta técnica no se podrá utilizar como se describe.


Sin embargo, hay una generalización significativamente más complicada de esta técnica, que no puede ser bloqueada Feature-Policyy que también permite que dominios completamente no relacionados compartan datos, comunicaciones y trabajadores compartidos (es decir, no solo subdominios de un superdominio común). @Mayank Jain ya lo describió en su respuesta, a saber:

La idea general es que, al igual que antes, cree un iframe oculto para proporcionar el origen correcto para el acceso; pero en lugar de simplemente tomar las propiedades de la ventana del iframe directamente, usa un script dentro del iframe para hacer todo el trabajo, y se comunica entre el iframe y su ventana principal solo usando postMessage()y addEventListener("message",...).

Esto funciona porque postMessage()se puede usar incluso entre ventanas de diferentes orígenes. Pero también es significativamente más complicado porque tienes que pasar todo a través de algún tipo de infraestructura de mensajería que creas entre el iframe y la ventana principal, en lugar de usar las API localStorage, IndexedDB, etc. directamente en el código de tu ventana principal.


0

Así lo resolví para mi sitio web. Redirigí todas las páginas sin www a www.site.com. De esta manera, siempre ocupará el almacenamiento local de www.site.com

Agregue lo siguiente a su .htacess , (cree uno si ya no lo tiene) en el directorio raíz

RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]

5
Estoy muy tentado a rechazar esto, pero no lo haré porque puede ayudar en el caso de uso del OP, pero para las personas que desean mantener sesiones en myapp.com y developers.myapp.com y support.myapp.com, esta respuesta es no está bien.
Don Omondi

Hola @DonOmondi ¡Te agradecería que me ayudases con los enlaces de lo que estás sugiriendo!
Ayush Baheti

3
El OP preguntó "use localStorage en todos los subdominios", su respuesta es "redireccionar www a no www" cosas muy diferentes, pero puede funcionar si y solo si el subdominio específico es "www.abc.com" para casos generales, algunas otras respuestas aquí son mas practico.
Don Omondi
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.