Database HTML5数据库和本地存储可以跨子域共享吗?

Database HTML5数据库和本地存储可以跨子域共享吗?,database,html,dns,subdomain,local-storage,Database,Html,Dns,Subdomain,Local Storage,我正在尝试使用Safari跨子域共享数据。我想使用HTML5数据库(特别是localStorage,因为我的数据只是键值对)。但是,似乎无法从sub.domain.com访问存储到domain.com的数据(反之亦然)。在这种情况下,有没有办法共享一个数据库?有一种简单的方法可以跨域使用任何东西,只需创建一个简单的页面,作为代理iframe包含在您尝试访问的域上,向该iframe发送PostMessage,并在iframe内执行本地存储数据库操作。这里是一个链接。这里是检查源代码,它使用ifra

我正在尝试使用Safari跨子域共享数据。我想使用HTML5数据库(特别是localStorage,因为我的数据只是键值对)。但是,似乎无法从sub.domain.com访问存储到domain.com的数据(反之亦然)。在这种情况下,有没有办法共享一个数据库?

有一种简单的方法可以跨域使用任何东西,只需创建一个简单的页面,作为代理iframe包含在您尝试访问的域上,向该iframe发送PostMessage,并在iframe内执行本地存储数据库操作。这里是一个链接。这里是检查源代码,它使用iframe和PostMessage


编辑:新建(由上面的演示使用)如果浏览器支持,请使用BroadcastChannel,但它仍然需要Iframe。最新版本还简化了跨源消息的使用,在repo中有iframe的html,可以使用(或者可以使用简单的html文件和带有lib的单个脚本标记),在父级中,只需调用一个函数
sysend.proxy('s)https://example.com');
其中example.com需要有
proxy.html
文件(您也可以使用自己的文件名和不同的路径)。

默认情况下,Google Chrome会阻止来自另一个域中iFrame的localStoage访问,除非启用了第三方cookie,iPhone上的Safari也启用了cookie…唯一的解决方案似乎是在另一个域上打开父域,然后通过window.postMessage发送给子域,但在手机上看起来很难看和变化无常…

Update 2016 这张来自Zendesk的照片对我有用

样本:

集线器

// Config s.t. subdomains can get, but only the root domain can set and del
CrossStorageHub.init([
  {origin: /\.example.com$/,            allow: ['get']},
  {origin: /:\/\/(www\.)?example.com$/, allow: ['get', 'set', 'del']}
]);
注意
$
用于匹配字符串的结尾。上面示例中的正则表达式将匹配源代码,例如
valid.example.com
,但不匹配
invalid.example.com.恶意.com

客户端

var storage = new CrossStorageClient('https://store.example.com/hub.html');

storage.onConnect().then(function() {
  return storage.set('newKey', 'foobar');
}).then(function() {
  return storage.get('existingKey', 'newKey');
}).then(function(res) {
  console.log(res.length); // 2
}).catch(function(err) {
  // Handle error
});
选中

是。这就是为什么: 对于给定超域的子域之间的共享(例如foo.example.com vs bar.example.com vs example.com),有一种技术可以在这种情况下使用。它可以应用于
localStorage
IndexedDB
SharedWorker
广播频道
等,所有这些都提供了相同来源页面之间的共享功能,但是出于某种原因,不要考虑对
document.domain
的任何修改,这将允许他们直接使用超级域作为其源

注意:此技术取决于设置
document.domain
,以允许不同子域上的iFrame之间进行直接通信。该功能现在已被弃用。(尽管截至2021年4月,它仍能在所有主要浏览器中工作,并且可能会保留以实现向后兼容性)。 (1) 为数据选择一个“主”域:即,或将保存本地存储数据。假设你选择了

(2) 对于所选域的页面,通常使用本地存储

(3) 在所有其他https://*.example.com页面(其他域)上,使用javascript设置
document.domain=“example.com”(始终为超级域)。然后还创建一个隐藏的
,并将其导航到所选域上的某个页面(无论是哪一页,只要你能在上面插入一小段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>
您可以通过在主页窗口中添加自定义“iframeredy”事件的侦听器来检测

(注意:即使iframe的域已经是example.com,也需要设置document.domain=“example.com”:将值赋给document.domain会隐式将源端口设置为null,并且两个端口必须匹配,iframe及其父端口才能被视为同一源。请参阅此处的说明:)

(五)一旦隐藏的iframe通知其父窗口它准备好了,父窗口中的脚本就可以使用
iframe.contentWindow.localStorage
iframe.contentWindow.indexedDB
iframe.contentWindow.BroadcastChannel
iframe.contentWindow.SharedWorker
,而不是
window.localStorage
window.indexedDB
,等等…所有这些对象的范围都将限定到所选的原点-因此它们将在您的所有页面上具有相同的共享原点

这种技术最棘手的部分是,您必须等待iframe加载后才能继续。因此,例如,您不能轻松地开始在DOMContentLoaded处理程序中使用localStorage。此外,您可能希望添加一些错误处理,以检测隐藏的iframe是否无法正确加载

显然,你也应该确保隐藏的iframe在你的页面生命周期内没有被删除或导航…我不知道这样会有什么结果,但很可能会发生不好的事情

还有一个警告:可以使用
功能策略
标题设置/更改
文档.域
阻止,在这种情况下,此技术将不可用


然而,这项技术有一个非常复杂的推广,不能被
特性策略    window.parent.dispatchEvent(new CustomEvent("iframeReady"));