Chrome 上的 Javascript 跨域异常,但 Firefox 上没有

问题描述

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

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

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


问题

其中大部分都有效,但是我在使用与 Firefox 扩展程序配合良好的特定网站时遇到了问题。

在此网站上,我试图获取一个位于 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 从 about:blank 更新到 https://subdomain.domain.fr/path3 时第二个 iframe 改变了它的域


问题

为什么在同一个域/子域中的 iframe 会引发异常?

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

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

解决方法

错误信息中说明了原因:

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

同源政策基于“tuple origin”术语:scheme + host + port + domain。起源通常是不可变的,只有元组起源的域可以改变,并且只能通过 document.domain API(端口号将额外重置为 null)。

原点为 https://subdomain.domain.fr:443 的框架之一将 document.domain 属性设置为 https://domain.fr:null
要允许它访问页面上的其他 iframe,您必须将 document.domain = "https://domain.fr" 设置为所有其他 iframe。或者,如果任何 iframe 和主窗口都可以使用 do not touch document.domain 属性。

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

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

Refused to run the JavaScript URL

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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...