javascript - 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:blank
域https://subdomain.domain.fr/path3
问题
为什么使用位于同一域/子域的 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
同源策略基于“元组起源”术语: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"
它们设置为所有。或者,如果可能的话,根本不要触摸 document.domain
任何 iframe 和主窗口的属性。
为什么您的代码在 Firefox 中有效而在 Chrome 中无效,这有点奇怪——两种浏览器的最新版本都document.domain
以相同的方式支持属性。
请注意该document.domain
属性已弃用,因此最好尽可能避免使用它。
Refused to run the JavaScript URL
看起来内容安全策略阻止了<a href='void(0)'>
构造。它不会阻止链接跟踪,只是阻止 javascript 执行。
推荐阅读
- java - 如何理解和优化工厂方法的高自时间
- ios - Swift:如何重用从 Nib 加载的自定义视图
- git - 两个 github 帐户推送到同一个 repo
- php - 将字段设置为 1,但如果它已经是 1,则将其设置为 NULL
- java - 架构演变上的 Avro 反序列化错误
- android - 如何在 Flutter 布局中固定间距
- java - 我需要从 Java 客户端发送服务器命令的语法
- javascript - 如何停止一次访问同一网站选项卡?
- java - 在字节和字符串之间进行转换时,是否应该始终在 Java 中显式提供编码?
- java - Java - 记录对象(CustomException)实例化的注释?