使用javascript跨域本地存储

IT技术 javascript local-storage cross-domain
2021-01-19 19:41:09

我们有一个 javascript api.js,它托管在域 api.abc.com 上。它管理本地存储。

我们将此 javascript 包含在我们的网站 abc.com 和 login.abc.com 中作为跨域 js,例如

<script src="http://api.abc.com/api.js">

我知道 localstoarge 是基于域的。但是,由于 api.js 是从 api.abc.com 加载的,我希望它可以从两个域访问 api.abc.com 的本地存储。不幸的是,情况似乎并非如此。当 api.js 从一个域将一个值存储在 localstoarge 中时,它在从其他域加载时无法访问。

任何的想法?

5个回答

如何使用跨域 postmessage 和 iframes?

因此,在您的错误域页面上包含一个 iframe,该 iframe 将带有 cookie 数据的消息发布回来。

这是跨域 postmessages 的一个可靠示例:http ://blog.teamtreehouse.com/cross-domain-messaging-with-postmessage

现场示例: http ://codepen.io/anon/pen/EVBGyz //分叉的发件人代码,有一个tiiiiiny变化:):

window.onload = function() {
    // Get the window displayed in the iframe.
    var receiver = document.getElementById('receiver').contentWindow;

    // Get a reference to the 'Send Message' button.
    var btn = document.getElementById('send');

    // A function to handle sending messages.
    function sendMessage(e) {
        // Prevent any default browser behaviour.
        e.preventDefault();

        // Send a message with the text 'Hello Treehouse!' to the new window.
        receiver.postMessage('cookie data!', 'http://wrong-domain.com');
    }

    // Add an event listener that will execute the sendMessage() function
    // when the send button is clicked.
    btn.addEventListener('click', sendMessage);
}

接收器代码:

window.onload=function(){
    var messageEle=document.getElementById('message');
    function receiveMessage(e){
        if(e.origin!=="http://correct-domain.com")
        return;
        messageEle.innerHTML="Message Received: "+e.data;
    }
    window.addEventListener('message',receiveMessage);
}

正如您在帖子中所注意到的,localStorage(也是 sessionStorage)不会存储在与域 api.abc.com 相关的存储中。如果是这种情况,通过使用 localStorage 使用库的 CDN 版本,您将必须与使用此库的所有其他网站共享存储。

一个好的解决方案可能是使用带有 postMessage 的 iframe,如以下堆栈溢出中所述: 跨子域使用 localStorage

确实,您的观点被采纳了,但是 CDN 通常是不同的域,我希望它在子域之间被允许,就像允许 cookie 一样。
2021-04-06 19:41:09

您可以从 Zendesk尝试这种跨存储基本上,有集线器和客户端:

  • 集线器:驻留在任何服务器上,直接与 LocalStorage API 交互

  • 客户端:使用嵌入式 iframe 加载集线器,发布消息,与数据交互

关键是您可以配置每个主机或域客户端可能拥有的权限(获取、设置、删除)。该库分为两种类型的组件:集线器和客户端。

应注意限制双向通信的来源。因此,在初始化集线器时,会传递一组权限对象。来自源与模式不匹配的客户端的任何消息都将被忽略,以及那些不在允许的方法集中的消息。由于同源策略,这组权限得以强制执行。但是,请记住,任何用户都可以完全控制他们的本地存储数据——它仍然是客户端数据。这仅限制每个域或 Web 应用程序级别的访问。

其他答案都忽略了这样一个事实,即您并不是真正在跨域操作,只是在子域之间操作。

你仍然需要一个隐藏的iframe来封装你想要访问的localStorage store的来源(api.abc.com),但是通过document.domain = "abc.com"在主窗口和隐藏的iframe上设置,它们可以直接交互。

然后你可以直接使用hiddenIFrame.contentWindow.localStorage而不是window.localStorage,而忘记通过 postMessage() 做任何事情的头痛。

我在此处发布了此答案的更详细版本:https : //stackoverflow.com/a/63602446/999120

使用 iframe 在本地存储和 postMessage API 中存储数据以在父域和 iframe 之间进行通信

  1. 使用消息事件侦听器创建 iframe 以将数据存储在 iframe 域的本地存储中

    window.addEventListener("message", handleMessage, false);
    
    function handleMessage(e) {
    let {key, value, method} = e.data;
    if (method == 'store') {
        window.localStorage.setItem(key, value); // Store data in iframe domain local storage
    } else if (method == 'retrieve') {
        let response = window.localStorage.getItem(key);
        e.source.postMessage({
            key,
            response,
            method: 'response'
        }, '*'); // Retrieve local storage data
    }
    

    }

  2. 将消息从父域传递到 iframe 以存储数据

    document.getElementById('myFrameId').contentWindow.postMessage({
    key: 'key',
    value: data,
    method: 'store'
    });
    
  3. 从 Iframe 检索数据

     document.getElementById('myFrameId').contentWindow.postMessage({
     method: 'response',
     key: 'key'
     });
    
     window.addEventListener("message", handleResponse, false);
    
     function handleResponse(e) {
      let {key,value,method} = e.data
      if (method == 'response') {
        console.log('Response Key', key);
        console.log('Response value', value)
      }
     }