Google chrome extension 将iframe注入具有限制性内容安全策略的页面

Google chrome extension 将iframe注入具有限制性内容安全策略的页面,google-chrome-extension,content-security-policy,Google Chrome Extension,Content Security Policy,我想创建一个浏览器扩展来创建一个侧栏。Chrome没有一流的侧边栏,因此我们必须在页面中添加iframe。但是,由于内容安全策略,这会在许多页面上中断。例如,GitHub使用CSP,不允许将来自其他站点的iFrame嵌入其中。例如,如果您试图将capitalone.com网站放在GitHub上的iframe中,您会得到以下结果: 拒绝对“”进行帧处理,因为它违反了以下内容安全策略指令:“frame src'self'render.githubusercontent.com www.youtube

我想创建一个浏览器扩展来创建一个侧栏。Chrome没有一流的侧边栏,因此我们必须在页面中添加iframe。但是,由于内容安全策略,这会在许多页面上中断。例如,GitHub使用CSP,不允许将来自其他站点的iFrame嵌入其中。例如,如果您试图将capitalone.com网站放在GitHub上的iframe中,您会得到以下结果:

拒绝对“”进行帧处理,因为它违反了以下内容安全策略指令:“frame src'self'render.githubusercontent.com www.youtube.com assets.braintreegateway.com”

这里有一个简单的浏览器扩展来重现:

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
  if (changeInfo.status === 'complete') {
   chrome.tabs.executeScript(tabId, { code: 'document.body.innerHTML=\'<iframe style=\"width:600px; height:600px\" src=\"https://www.capitalone.com/\"></iframe>\' + document.body.innerHTML;' }, function() {
     console.log('Iframe injection complete');
   })
  }
}.bind(this));
chrome.tabs.onUpdate.addListener(函数(tabId、changeInfo、tab){
如果(changeInfo.status==‘完成’){
chrome.tabs.executeScript(tabId,{code:'document.body.innerHTML=\'\'\'+document.body.innerHTML;'},function(){
console.log(“Iframe注入完成”);
})
}
}.约束(这个);
然而,根据Wikipedia的说法,浏览器扩展应该能够插入iframe,尽管有任何内容安全策略:

根据CSP处理模型,[20]CSP不应干扰用户安装的浏览器附加组件或扩展的操作。CSP的此功能有效地允许任何附加组件或扩展将脚本注入网站,而不管脚本的来源如何,因此不受CSP策略的约束


除了我正在做的事情之外,还有其他方法可以注入iframe吗?

无法在Chrome中插入外部iframe是一个bug()

如果要在外部网站中嵌入外部框架,则必须将其加载到与扩展打包在一起的框架中

manifest.json
{
“名称”:“嵌入外部站点”,
“版本”:“1”,
“清单版本”:2,
“内容脚本”:[{
“js”:[“contentscript.js”],
“匹配项”:[“*://*/*”],
“所有帧”:正确
}],
“网络可访问资源”:[
“frame.html”
]
}
如果希望在文档中始终插入内容脚本,请不要使用
chrome.tabs.onUpdate
+
chrome.tabs.executeScript
。您的实现有缺陷,可能导致脚本运行多次。相反,你应该这样做

(如果不想在每个子帧中插入帧,请删除
“所有帧”:true
。)

contentscript.js
//避免递归帧插入。。。
var extensionOrigin='chrome extension://'+chrome.runtime.id;
如果(!location.ancestorOrigins.contains(extensionOrigin)){
var iframe=document.createElement('iframe');
//必须在manifest.json中的web_accessible_资源中声明
iframe.src=chrome.runtime.getURL('frame.html');
//花式侧边栏的一些样式
iframe.style.cssText='位置:固定;顶部:0;左侧:0;显示:块;'+
'宽度:300px;高度:100%;z指数:1000;';
document.body.appendChild(iframe);
}
frame.html

html,body,iframe,h2{
保证金:0;
边界:0;
填充:0;
显示:块;
宽度:100vw;
高度:100vh;
背景:白色;
颜色:黑色;
}
氢{
高度:50px;
字体大小:20px;
}
iframe{
高度:计算(100vh-50px);
}
展示https://robwu.nl 相框
我在框架中加载了一个
https
站点,这一点很重要。如果尝试在帧中加载HTTP站点,则如果父帧之一是https页面,则混合内容策略将阻止加载该帧

替换
https://robwu.nl/
http://example.com/
,在https页面上,框架将保持空白,例如。同时,以下消息将打印到控制台

[已阻止]页面位于'https://github.com/'通过HTTPS加载,但从运行不安全的内容'http://example.com/“:此内容也应通过HTTPS加载


您的示例应该在Chrome中工作,但由于一个bug,目前无法工作:。Rob W的答案包含了一个很好的解决方案。

Rob W的答案是正确的。你可以跟着这个。我已经成功地使它在我的Chrome扩展中工作

请注意,我使用的是Chrome59,因此我可以使用ES6的大部分功能

在清单中声明

"web_accessible_resources": [
  "iframe.html",
  "scripts/iframe.js"
]
let url    = decodeURIComponent(window.location.search.replace('?url=', ''))
let iframe = document.createElement('iframe')
iframe.src = url

iframe.id = 'github-chat-box-iframe-inner'
iframe.style.width = '100%'
iframe.style.height = '350px'
iframe.style.border = '0px'

window.onload = () => {
  document.body.appendChild(iframe)
}
在window.onload事件中创建iframe

"web_accessible_resources": [
  "iframe.html",
  "scripts/iframe.js"
]
let url    = decodeURIComponent(window.location.search.replace('?url=', ''))
let iframe = document.createElement('iframe')
iframe.src = url

iframe.id = 'github-chat-box-iframe-inner'
iframe.style.width = '100%'
iframe.style.height = '350px'
iframe.style.border = '0px'

window.onload = () => {
  document.body.appendChild(iframe)
}

嗨,罗布,谢谢你的回答。我想注入一个从我的服务器加载的脚本,这样我就可以处理更新而不必推送新的扩展。不幸的是,这意味着我无法将其捆绑为内容脚本。我可以做一些类似的事情,比如让一个简单的内容脚本从我的服务器接受动态加载的脚本并运行它吗?@Benmcann您可以使用
XMLHttpRequest
获取脚本,使用存储脚本,并在内容脚本中使用
eval
,或者从后台页面执行内容脚本。我之前在上发布了这个概念的具体实现。有没有办法动态设置内部iframe src元素(src=“)?@cnmuc Yes。将
放在文档末尾,然后在脚本文件(script.js)中分配给
.src
。例如
文档.querySelector('iframe')).src='1https://example.com“;
Chrome bug被标记为已通过目标Chrome版本v75修复(这意味着将在不久的将来发布,就像我们在v73上一样)。请注意,问题正在解决,问题是关于frame src CSP。问题状态为已修复()-但我刚刚在Chrome 84上测试过-它仍然存在:(出于安全原因,一些web服务器配置为防止嵌入iFrame(X-FRAME-OPTIONS)。我使用Chrome 84测试了一个测试页面(),能够从注入的iFrame加载页面。