我在可以支持它的浏览器上替换localStorage的cookie(除了IE之外的任何人)。问题是 site.com 和 www 。 site.com 存储他们自己独立的localStorage对象。我相信www被认为是一个子域名(如果你问我,这是一个愚蠢的决定)。如果用户最初访问 site.com 并决定在下次访问时输入 www 。 site.com ,那么她的所有个人数据都会无法进入。如何让所有“子域”与主域共享相同的localStorage?
答案 0 :(得分:73)
这就是我跨域使用它的方式......
我希望它有所帮助:)
答案 1 :(得分:28)
如果您仅针对此特定问题使用iframe和postMessage解决方案,我认为仅将数据存储在子域中的工作(代码和计算方面)可能更少更少的cookie,如果它在加载的localStorage中已经没有了,请从cookie中抓取它。
我同意其他评论者的观点,这似乎应该是localStorage的可选选项,因此不需要解决方法。
答案 2 :(得分:26)
我建议将site.com重定向到www.site.com,以保持一致性和避免此类问题。
另外,请考虑使用可以使用每个浏览器本机存储的PersistJS等跨浏览器解决方案。
答案 3 :(得分:12)
设置为主域中的cookie-
document.cookie = "key=value;domain=.mydomain.com"
然后从任何主域或子域中获取数据,并将其设置在localStorage上
答案 4 :(得分:3)
我使用的是xdLocalStorage,这是一个轻量级的js库,它使用iframe后置消息通信实现LocalStorage接口并支持跨域存储。(angularJS支持)
答案 5 :(得分:3)
[ 2020年11月更新: 此解决方案依赖于能够设置document.domain
。不幸的是,现在已经不赞成这样做。]
要在给定超域的子域之间进行共享(例如example.com),可以在这种情况下使用一种技术。它可以应用于localStorage
,IndexedDB
,SharedWorker
,BroadcastChannel
等,所有这些元素在同源页面之间提供共享功能,但是由于某些原因不尊重对document.domain
的任何修改,这些修改将允许他们直接使用超域作为其起源。
(1)选择一个“主”域作为数据所属的域:即 https://example.com 或 https://www.example.com 将保留您的localStorage数据。假设您选择https://example.com。
(2)通常在所选域的页面上使用localStorage。
(3)在所有 https://www.example.com 页面( other 域)上,使用javascript设置document.domain = "example.com";
。然后还创建一个隐藏的<iframe>
,并将其导航到所选 https://example.com 域上的 some 页面( < em>什么页面,只要您可以在其中插入一小段javascript代码即可。如果您要创建网站,则只需为此专门制作一个空白页面即可。编写扩展程序或Greasemonkey风格的用户脚本,因此对 example.com 服务器上的页面没有任何控制权,只需选择可以找到的最轻巧的页面并将脚本插入其中即可。种类的“未找到”页面可能会很好)。
(4)隐藏的iframe页面上的脚本仅需要(a)设置document.domain = "example.com";
,并且(b)完成后通知父窗口。之后,父窗口可以不受限制地访问iframe窗口及其所有对象!因此,最小的iframe页面类似于:
<!doctype html>
<html>
<head>
<script>
document.domain = "example.com";
window.parent.iframeReady(); // function defined & called on parent window
</script>
</head>
<body></body>
</html>
如果编写用户脚本,则可能不希望将iframeReady()
之类的可外部访问的功能添加到unsafeWindow
中,因此,通知主窗口用户脚本的一种更好的方法可能是使用自定义事件:
window.parent.dispatchEvent(new CustomEvent("iframeReady"));
您会通过在首页窗口中添加自定义“ iframeReady”事件的侦听器来进行检测。
(注意:即使iframe的域已经是 example.com ,也需要设置document.domain =“ example.com”:为document.domain分配一个值会隐式设置来源的 port 设置为null,并且两个端口都必须匹配,才能将iframe及其父代视为相同来源。请参见此处的注释:https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#Changing_origin)
(5)一旦隐藏的iframe通知其父窗口已经准备好,父窗口中的脚本就可以使用iframe.contentWindow.localStorage
,iframe.contentWindow.indexedDB
,iframe.contentWindow.BroadcastChannel
,iframe.contentWindow.SharedWorker
而不是window.localStorage
,window.indexedDB
等。所有这些对象的作用域将是选定的 https://example.com 原点-因此它们将具有您所有页面的共享来源相同!
此技术最尴尬的部分是,您必须等待iframe加载后才能继续。因此,例如,您不能仅仅在DOMContentLoaded处理程序中轻松地开始使用localStorage。另外,您可能需要添加一些错误处理,以检测隐藏的iframe是否无法正确加载。
很显然,您还应该确保在页面生命周期中未删除或导航隐藏的iframe ... OTOH我不知道这样做的结果是什么,但很可能会发生坏事。 / p>
而且,需要警告:可以使用document.domain
标头阻止设置/更改Feature-Policy
,在这种情况下,该技术将无法按所述使用。
但是,这种技术的概括要复杂得多,Feature-Policy
不能阻止它,并且允许完全不相关的域共享数据,通信和共享的工作器< / strong>(即不只是普通超级域的子域)。 @Mayank Jain已经在回答中对此进行了描述,即:
通常的想法是,如上所述,您创建了一个隐藏的iframe,以提供正确的访问源;但是,您不仅可以直接获取iframe窗口的属性,还可以在iframe中使用脚本来完成所有工作,并且仅使用postMessage()
和addEventListener("message",...)
在iframe和主窗口之间进行通信。 / p>
之所以可行,是因为postMessage()
甚至可以在不同来源的窗口之间使用。但这也要复杂得多,因为您必须将所有内容都通过在iframe和主窗口之间创建的某种消息传递基础结构传递,而不是仅在主窗口的代码中直接使用localStorage,IndexedDB等API。>
答案 6 :(得分:1)
这就是我为我的网站解决的问题。我将没有www的所有页面重定向到www.site.com。这样,它将始终采用www.site.com的本地存储
将以下内容添加到 .htacess 中,(如果您还没有,请创建一个)根目录
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
答案 7 :(得分:1)
这种解决方案会导致许多类似问题。出于一致性和SEO考虑 在主域上重定向是最好的解决方案。
在服务器级别进行重定向
如何使用Nginx将www重定向到非www
或 任何其他级别,例如使用
的Route 53答案 8 :(得分:-15)
您可以使用document.domain
属性。如果你把它放在JavaScript的第一个动作中:
document.domain="mysite.com";