【问题标题】:Is there any workaround to make use of html5 localstorage on both http and https?是否有任何解决方法可以在 http 和 https 上使用 html5 本地存储?
【发布时间】:2012-05-17 03:56:40
【问题描述】:

我需要在客户端存储一些数据,而这些数据太大而无法将其存储在 cookie 中。 LocalStorage 似乎是这样做的完美方式,但问题是我将使用它的网站有一些部分可以在 https 上工作,而其他部分只能在 http 上工作,因为本地存储无法从你用 http 设置的 https 访问数据这似乎不再是一个可行的解决方案。

知道是否有任何解决方案吗?还有其他选择吗?

【问题讨论】:

标签: html local-storage


【解决方案1】:

将所有数据存储在一个域中,例如https://my.domain.org/.

  • https 协议上,只需使用localStorage.setItem('key', 'value') 来保存数据。
  • http 协议上,嵌入https 框架,并使用postMessage 保存数据:

演示http://jsfiddle.net/gK7ce/4/(帮助页面位于http://jsfiddle.net/gK7ce/3/)。

// Script at https://my.domain.org/postMessage
window.addEventListener('message', function(event) {
    // Domain restriction (to not leak variables to any page..)
    if (event.origin == 'http://my.domain.org' ||
        event.origin == 'https://my.domain.org') {
        var data = JSON.parse(event.data);
        if ('setItem' in data) {
            localStorage.setItem(data.setItem, data.value);
        } else if ('getItem' in data) {
            var gotItem = localStorage.getItem(data.getItem);
            // See below
            event.source.postMessage(
                '#localStorage#' + data.identifier + 
                (gotItem === null ? 'null#' : '#' + gotItem),
                event.origin
            );
        } else if ('removeItem' in data) {
            localStorage.removeItem(data.removeItem);
        }
    }
}, false);

在 http(s) 页面上,可以按如下方式嵌入框架(https://my.mydomain.com 替换为实际 URL。请注意,您可以简单地获取对框架的引用,然后使用src属性):

<iframe name="myPostMessage" src="https://my.domain.org/postMessage" style="display:none;"></iframe>
// Example: Set the data
function LSsetItem(key, value) {
    var obj = {
        setItem: key,
        value: value
    };
    frames['myPostMessage'].postMessage(JSON.stringify(obj), 'https://my.domain.com');
}
LSsetItem('key', 'value');

注意该方法是异步的,因为postMessagegetItem 方法的实现必须以不同的方式实现:

var callbacks = {};
window.addEventListener('message', function(event) {
    if (event.source === frames['myPostMessage']) {
        var data = /^#localStorage#(\d+)(null)?#([\S\s]*)/.exec(event.data);
        if (data) {
            if (callbacks[data[1]]) {
                // null and "null" are distinguished by our pattern
                callbacks[data[1]](data[2] === 'null' ? null : data[3]);
            }
            delete callbacks[data[1]];
        }
    }
}, false);
function LSgetItem(key, callback) {
    var identifier = new Date().getTime();
    var obj = {
        identifier: identifier,
        getItem: key
    };
    callbacks[identifier] = callback;
    frames['myPostMessage'].postMessage(JSON.stringify(obj), 'https://my.domain.com');
}
// Usage:
LSgetItem('key', function(value) {
    console.log('Value: ' + value);
});

请注意,每个回调都存储在哈希中。每条消息还包含一个标识符,以便接收消息的窗口调用正确的相应回调。

为了完整起见,这里是LSremoveItem 方法:

function LSremoveItem(key) {
    var obj = {
        removeItem: key
    };
    frames['myPostMessage'].postMessage(JSON.stringify(obj), 'https://my.domain.com');
}

【讨论】:

  • 我试过了,但是当 https iframe 尝试将消息发送回 http 父窗口时,我收到错误消息“不安全的 JavaScript 尝试使用 URL 访问框架...域、协议和端口必须匹配。”有什么想法吗?
  • 是的,做了更多的测试,似乎它确实有效。我的问题是由另一个注入的脚本引起的。感谢您的帮助。
  • 这是一个聪明的解决方案,但它已停止在 iOS 7/Safari 上运行。现在还有其他人有这个问题吗?本地存储似乎使用父窗口的协议而不是 iframe。有人有新的答案可以贡献吗?
  • @robC Safari 的问题是由“阻止 cookie 和其他网站数据”首选项引起的。当它设置为“来自第三方和广告商”时,localStorage 不再共享。必须设置为“从不”,如下图所示:i.stack.imgur.com/AP4ed.png
猜你喜欢
  • 2011-03-18
  • 2019-09-05
  • 2011-06-09
  • 1970-01-01
  • 2019-04-08
  • 1970-01-01
  • 2016-03-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多