成功调用requestStorageAccess()后,Firefox Storage Access API拒绝本地存储

时间:2019-01-11 16:01:40

标签: javascript firefox cookies iframe same-origin-policy

我想测试新的Firefox Storage Access API,以允许第一方存储(cookie,本地存储,indexeddb等)到其他域的iframe(但仍在我的控制之下)。

父标记/代码

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Parent Domain</title>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/js-cookie/2.2.0/js.cookie.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jschannel/1.0.0-git-commit1-8c4f7eb/jschannel.min.js"></script>
    </head>
    <body>
        <div>
            Cookies: <ul class="cookie-data"></ul>
        </div>
        <iframe 
            id="rpc-gateway"
            src="http://child.local:8080/iframe-firefox.html"
            sandbox="allow-storage-access-by-user-activation allow-scripts allow-same-origin"></iframe>
        <script type="text/javascript">            
            var chan = Channel.build({
                window: document.getElementById("rpc-gateway").contentWindow,
                origin: "*",
                scope: "testScope"
            });
        </script>
    </body>
</html>

子iframe标记/代码

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Child Domain</title>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/js-cookie/2.2.0/js.cookie.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jschannel/1.0.0-git-commit1-8c4f7eb/jschannel.min.js"></script>
    </head>
    <body>
        <button onClick="onLoginClick()">Login</button>
        <script type="text/javascript">
            var chan = Channel.build({
                window: window.parent,
                origin: "*",
                scope: "testScope"
            });

            let onLoginClick = function(trans, params) {
                document.hasStorageAccess().then(hasAccess => {
                    if (!hasAccess) {
                        console.log("no access - requesting access");
                        return document.requestStorageAccess();
                    }
                }).then(_ => {
                    document.hasStorageAccess().then(hasAccess => {
                        console.log("hasAccess:", hasAccess);
                        window.localStorage.setItem('foo', 'bar');
                    })
                }).catch((err) => {
                    console.log("hasStorageAccess() failed", err);
                });
            };
        </script>
    </body>
</html>

在子iframe中单击“登录”按钮时,将生成以下日志输出:

no access - requesting access      # iframe-firefox.html:22:25
hasAccess: true      # iframe-firefox.html:27:25
Request to access cookie or storage on “http://child.local:8080/iframe-firefox.html” was blocked because we are blocking all third-party storage access requests and content blocking is enabled.      # iframe-firefox.html:28:24

可见的结论是:

  • promise document.hasStorageAccess()解析
  • hasAccess参数最初为“ false”
  • 返回document.requestStorageAccess()的承诺并解决
  • 第二个承诺文档。hasStorageAccess()解决了
  • hasAccess参数现在为'true'
  • 不过,无法通过简单的存储访问本地存储。

我该怎么办?

更多信息:

  • Firefox开发人员版65.0b9
  • 内容阻止设置:Content Blocking Setting

1 个答案:

答案 0 :(得分:0)

这似乎是您使用的Firefox版本中的错误。我在本地设置了一个测试,并使用Firefox 69.0.1(64位)进行了测试,没有错误,并且该值存储在本地存储中。当我从父级iframe中取出沙箱标志allow-storage-access-by-user-activation时,子级未能获得对本地存储的许可,因此可以确认我的设置实际上在正常工作。这是我所做的:

为父级创建Node.js / Express服务器:

const express = require('express');
const cors = require('cors');
const path = require('path');
const server = express();

server.use(cors());
server.use(express.static(path.resolve('./public')));

server.listen(8080, function() {
  console.log('listening on *:8080');
});

为子节点创建一个Node.js / Express服务器(具有不同的端口以触发相同的原始策略):

const express = require('express');
const cors = require('cors');
const path = require('path');
const server = express();

server.use(cors());
server.use(express.static(path.resolve('./public')));

server.listen(8081, function() {
  console.log('listening on *:8081');
});

为父级创建了一个index.html(与您的父级几乎相同):

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Parent Domain</title>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/js-cookie/2.2.0/js.cookie.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jschannel/1.0.0-git-commit1-8c4f7eb/jschannel.min.js"></script>
    </head>
    <body>
        <div>
            Cookies: <ul class="cookie-data"></ul>
        </div>
        <iframe
            id="rpc-gateway"
            src="http://127.0.0.1:8081/iframe-firefox.html"
            sandbox="allow-storage-access-by-user-activation allow-scripts allow-same-origin"></iframe>
        <script type="text/javascript">
            var chan = Channel.build({
                window: document.getElementById("rpc-gateway").contentWindow,
                origin: "*",
                scope: "testScope"
            });

            // Added this to try out the JSChannel
            chan.call({
                method: "reverse",
                params: "hello world!",
                success: function(v) {
                    console.log(v);
                }
            });

        </script>
    </body>
</html>

并为孩子创建了iframe-firefox.html:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Child Domain</title>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/js-cookie/2.2.0/js.cookie.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jschannel/1.0.0-git-commit1-8c4f7eb/jschannel.min.js"></script>
    </head>
    <body>
        <button onClick="onLoginClick()">Login</button>
        <script type="text/javascript">
            var chan = Channel.build({
                window: window.parent,
                origin: "*",
                scope: "testScope"
            });

            // Other end of the JSChannel call
            chan.bind("reverse", function(trans, s) {
                return s.split("").reverse().join("");
            });

            let onLoginClick = function(trans, params) {
                document.hasStorageAccess().then(hasAccess => {
                    if (!hasAccess) {
                        console.log("no access - requesting access");
                        return document.requestStorageAccess();
                    }
                }).then(_ => {
                    document.hasStorageAccess().then(hasAccess => {
                        console.log("hasAccess:", hasAccess);
                        window.localStorage.setItem('foo', 'bar');
                    })
                }).catch((err) => {
                    console.log("hasStorageAccess() failed", err);
                });
            };
        </script>
    </body>
</html>

一切都按预期进行了...因此,我非常确定问题出在与您使用的特定版本的Firefox Developer Edition有关。

此外,如果您想尝试一下该设置的zip链接,请参见以下链接:server.zip

让我知道我还有什么可以帮助您的。