我试图将一个站点嵌入另一个站点。我控制两台服务器,我将在这里称为“site1.com”(浏览器中的站点)和“site2.com”(我试图嵌入的站点)。
尝试1,使用iframe标记:
<iframe height="600" width="600" name="my other site"
src="https://site2.com/foo/bar">
Unable to display--your browser does not support frames.
</iframe>
尝试2,使用object标签:
<object type="text/html" height="600" width="600" name="my other site"
data="https://site2.com/foo/bar"></object>
我已经读过Firefox不允许将HTTP嵌入到HTTPS页面中。这两个站点都是HTTPS,因此没有不匹配。加载的资源(CSS等)也是来自同一来源的https,因此没有混合内容问题。
我已经尝试将security.mixed_content.block_active_content
设置为false
,以防我误解为此,但iframe仍然是空白的。
这两个站点都使用有效的证书,由适当的受信任机构签名,并且未过期。实际上,我们使用的是子域通配符证书,因此它们都使用相同的证书(它们都在同一个子域中)。
我想要嵌入的网站有这个响应头:
X-Frame-Options: ALLOW-FROM SITE1.COM
我试图嵌入的网站有这个响应标题(为了便于阅读而包含在这里):
Content-Security-Policy:
frame-ancestors https://site1.com;
default-src 'self';
script-src https://site1.com 'self' 'unsafe-inline';
style-src https://site1.com 'self' 'unsafe-inline'
额外的披露,可能不需要 - 这些头文件是由Django应用程序服务器使用此配置和“django-csp”模块生成的。
X_FRAME_OPTIONS = 'Allow-From site1.com'
CSP_FRAME_ANCESTORS = ('https://site1.com',)
CSP_STYLE_SRC = ('https://site1.com', "'self'", "'unsafe-inline'")
CSP_SCRIPT_SRC = ('https://site1.com', "'self'", "'unsafe-inline'")
我的理解是,当请求包含“Origin”标头时,CORS才会起作用。这似乎没有发生在这里。我也试过使用这个头来解决CORS问题:
Access-Control-Allow-Origin: https://site1.com
但这似乎没有效果。
我在这个Firefox安装中没有广告拦截器。我还删除了所有扩展并在Firefox重启后重新测试,“空白iframe”行为保持不变,根本没有安装扩展。
我已使用以下浏览器进行了测试。
使用Chrome,Safari和Edge,框架显示如我所料 - site2.com显示为site1.com页面内的一个框。
使用Firefox,我显示一个指定大小(600x600)的空白空间。如果我使用iframe,那么它周围会出现黑色边框。如果我使用了对象,它只是一个没有边框的空白区域。
最有趣的是,如果我打开开发人员控制台并重新加载页面,我会看到获取site1.com及其CSS等的请求,但是没有针对site2.com的请求。这不是显示site2.com的问题,它根本就没有被要求。
此外,开发人员控制台不会显示任何错误或警告。如果出现错误情况或安全异常阻止加载第二个站点,我希望记录某种警告。
这让我疯狂了好几天。任何建议赞赏。
我在我的服务器上重现了这个问题,该服务器提供2个域,然后以这种方式修复它:
X-Frame-Options: ALLOW-FROM https://SITE1.COM
我添加了https://
,如MDN page for X-Frame-Options所见
你可以在这里观察差异(当然只有Firefox,就像其他浏览器一样显示两个框架):我推了一个插入标题without或with https://
的php页面,并创建了插入2个iframe的this fiddle:Firefox显示第一个iframe为在右边有空的,第二个有内容(在标题中回显值)。
由于您被迫放置“序列化原点”(协议+ FQDN),我想知道您是否可以放置多个条目或通配符。我对RFC 7034的理解说你做不到。
现在关于这个细节:
最有趣的是,如果我打开开发人员控制台并重新加载页面,我会看到获取site1.com及其CSS等的请求,但是没有针对site2.com的请求。这不是显示site2.com的问题,它根本就没有被要求。
那是因为它被缓存了。我也看到了这一点,但强制刷新正确地显示了一个新的请求。
如果您知道源代码(右键单击并查看要嵌入的URL的源代码 - 但在这种情况下您可以控制它以便复制和粘贴)并且它只是相当少量的代码(可能因为您使用的是iframe ),然后你可以使用HTML5 srcdoc属性来嵌入html代码,而不是指向url。对于你想要嵌入的网站(CORS等)的未知因素,这将节省很多麻烦,如果你无法控制第二个网站,你通常不会知道。
根据caniuse.com的说法,自从vsn 25开始以来,srcdoc
财产在Firefox中得到了全面支持(因此自2013年9月起)。
希望这会有所帮助(这是一个经过测试的jsfiddle示例)