首页 > 解决方案 > Chrome 上的 Javascript 跨域异常,但 Firefox 上没有

问题描述

我最近开发了一个 Firefox 扩展,它允许我在几个网站上自动执行一些操作(主要是检索数据)。

该扩展程序运行良好,因此我目前正在开发该扩展程序的 Chrome 版本。

Chrome 和 Firefox 扩展程序之间存在一些差异,但它们主要是在两个扩展程序中运行的相同代码。


问题

大部分都有效,但是我在与 Firefox 扩展配合良好的特定网站上遇到了麻烦。

在这个网站上,我正在尝试获取一个位于 iframe 中的表格,该 iframe 本身位于另一个 iframe 中。

访问第二个 iframe 时,我面临以下异常。

Uncaught SecurityError: Blocked a frame with origin "https://subdomain.domain.fr" from accessing a frame with origin "https://subdomain.domain.fr". The frame requesting access set "document.domain" to "domain.fr", but the frame being accessed did not. Both must set "document.domain" to the same value to allow access

页面结构如下

<iframe id="iframe_centrale" src="/[...]">
    [...]
    <iframe id="iframe" src="/[...]">
        [...]
        <table></table>
        [...]
    </iframe>
    [...]
</iframe>

我正在尝试按如下方式访问 iframe

var tableElement = null;
var iframe = null;
iframe = document.getElementById('iframe_centrale');
if(null != iframe)
{
    iframe = iframe.contentWindow.document.getElementById("iframe");
    if(null != iframe)
    {
        tableElement = iframe.contentWindow.document.evaluate("//table", iframe.contentDocument, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
        if((null != tableElement)
        {
            // Read table
        }
    }
}

问题分析

尝试访问位于另一个域上的资源时,通常会遇到触发的异常。

但是在我的情况下,两个 iframe 都位于同一个域中,因为该src属性是一个相对 url。

完全相同的代码在 Firefox 上正常工作的事实也证实了我可以访问第二个 iframe。


更多信息

我面临的另一个错误是,在浏览过程中,我填写了一个位于 iframe 中的表单,并且触发了一次以下异常,但是表单仍然正确填写。

Uncaught DOMException: Blocked a frame with origin "https://subdomain.domain.fr" from accessing a cross-origin frame.

由于它在突变观察者循环中,该指令可能会第二次起作用,它可以解释为什么填写表格。

填写表格后,我单击一个按钮,进入一个 iframe,本身进入一个 iframe。单击按钮时,我有以下异常

Refused to run the JavaScript URL because it violates the following Content Security Policy directive: "script-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution

再一次,点击进入一个突变观察者循环,因此它可能被触发一次,然后工作,但我被重定向到下一页,所以点击工作。


从 Firefox 调查

由于我可以从 Firefox 访问两个 iframe 的内容,因此我尝试打印基本文档和两个 iframe 的“域”和“url”信息。

#############################################################
### BASE PAGE : domain.fr / https://subdomain.domain.fr/path1
### IFRAME 1 : domain.fr / https://subdomain.domain.fr/path2
TypeError: iframe2 is null

[...]

#############################################################
### BASE PAGE : domain.fr / https://subdomain.domain.fr/path1
### IFRAME 1 : domain.fr / https://subdomain.domain.fr/path2
### IFRAME 2 : domain.fr / about:blank

[...]

#############################################################
### BASE PAGE : domain.fr / https://subdomain.domain.fr/path1
### IFRAME 1 : domain.fr / https://subdomain.domain.fr/path2
### IFRAME 2 : subdomain.domain.fr / https://subdomain.domain.fr/path3

所以我认为问题正在发生,因为当 url 更新为时,第二个 iframe 更改了它的about:blankhttps://subdomain.domain.fr/path3


问题

为什么使用位于同一域/子域的 iframe 会触发异常?

是否有其他方法可以访问第二个 iframe 内容并使用 Chrome 对其进行操作?

有人知道为什么这段代码适用于 Firefox 但不适用于 Chrome 吗?

标签: javascriptiframegoogle-chrome-extensionfirefox-addon-webextensionscross-domain-policy

解决方案


错误消息中说明了原因:

The frame requesting access set "document.domain" to "domain.fr", but the frame being
accessed did not. Both must set "document.domain" to the same value to allow access

同源策略基于“元组起源”术语:scheme+ host+ port+ domain。来源通常是不可变的,只能更改元组来源的域,并且只能通过document.domainAPI(端口号将另外重置为null)。

您的一个带有原点的框架https://subdomain.domain.fr:443document.domain属性设置为https://domain.fr:null.
要允许它访问页面上的其他 iframe,您必须将document.domain = "https://domain.fr"它们设置为所有。或者,如果可能的话,根本不要触摸 document.domain任何 iframe 和主窗口的属性。

为什么您的代码在 Firefox 中有效而在 Chrome 中无效,这有点奇怪——两种浏览器的最新版本都document.domain以相同的方式支持属性。

注意document.domain属性已弃用,因此最好尽可能避免使用它。

Refused to run the JavaScript URL

看起来内容安全策略阻止了<a href='void(0)'>构造。它不会阻止链接跟踪,只是阻止 javascript 执行。


推荐阅读