【问题标题】:Injecting remote iframe with Chrome extension使用 Chrome 扩展注入远程 iframe
【发布时间】:2018-05-03 20:51:33
【问题描述】:

在我的一生中,我无法让 Chrome 扩展程序显示带有远程 URL 的 iframe。

我在控制台中看到以下消息 -

拒绝框架“https://www.example.com/”,因为它违反了以下内容安全策略指令:“child-src 'self'”。请注意,'frame-src' 没有显式设置,因此 'child-src' 用作后备。

我在这里 (Injecting iframe into page with restrictive Content Security Policy) 找到了一个解决方案,它需要注入一个本地 iframe,然后再将另一个 iframe 引用到远程 url。这应该绕过sontent安全策略。但由于某种原因,它似乎不适用于我的情况。是我遗漏了什么还是 chrome 安全政策发生了变化?

以下是与此问题相关的我的扩展部分。注意 - 这段代码不是最漂亮的,因为我一直在尝试让它工作。

目前的工作方式是 background.js 向 inject.js 发送消息。 inject.js 插入第一个 iframe,引用本地文件 infobar.html。该页面是我们的主要用户界面,我们希望将远程 html 页面显示在 iframe 中作为该页面的一部分。然后 infobar.js 插入一个引用本地文件 frame.html 的 iframe。最后,frame.html 有一个 iframe 硬编码到我们的远程 url。

根据之前的答案,只有第一个 iframe 应该受内容安全策略的约束。但是,这里的情况似乎并非如此,因为引用 example.com 的那个实际上是 3 个 iframe 深。

ma​​nifest.json

{
...
  "content_security_policy": "script-src 'self'; object-src 'self'; frame-src https://www.example.com; child-src https://www.example.com",
  "background": {
    "scripts": [
      "js/jquery/jquery.min.js",
      "src/bg/background.min.js"
    ],
    "persistent": true
  },
...
  "content_scripts": [
    {
      ...
      "css": [
        ...
        "src/inject/inject.min.css"
      ],
      "js": [
        ...
        "src/inject/inject.min.js"
      ]
    }
  ],
  "externally_connectable": {
    "matches": [
      "*://localhost/*",
      "*://*.example.com/*
    ]
  },
  "web_accessible_resources": [
    "src/inject/inject.html",
    "src/inject/infobar.html",
    "src/inject/infobar.min.js",
    "src/inject/frame.html"
  ],
  "sandbox": {
    "pages": [
      "src/inject/infobar.html",
      "src/inject/frame.html"
    ]
  }
}

inject.js

var iframe = document.createElement("iframe");
iframe.scrolling = "no";
iframe.style.cssText = "display:none;";
...
$(iframe).load(function () {
    var message = {
        command: "render-frame",
        context: data,
        frameUrl: chrome.runtime.getURL("src/inject/frame.html")
    };
    iframe.contentWindow.postMessage(message, '*');
    iframe.style.cssText = "border: 0px; overflow: visible; padding: 0px; right: auto; width: 100%; height: " + toolbarHeight + "px; top: 0px; left: 0px; z-index: 2147483647; box-shadow: rgba(0, 0, 0, 0.498039) 0px 3px 10px; position: fixed; display: none;";
});
...
iframe.src = chrome.runtime.getURL("src/inject/infobar.html");      
...     
document.documentElement.appendChild(iframe);  

infobar.html

简单的 HTML 页面。里面没有什么相关的。参考 infobar.js。

infobar.js

window.addEventListener("message", function (event) {
    var command = event.data.command;
    switch (command) {
        case "render-frame":
            var frame = document.createElement("iframe");
            frame.scrolling = "no";
            frame.src = event.data.frameUrl;
            document.getElementById("content").appendChild(frame); 
...
            break;
    }
});

frame.html

<html>
<head>
    <style>
        html, body, iframe, h2 {
            margin: 0;
            border: 0;
            padding: 0;
            display: block;
            width: 100vw;
            height: 100vh;
            background: white;
            color: black;
        }
    </style>
</head>
<body>
<iframe src="https://www.example.com/page.html"></iframe>
</body>
</html>

【问题讨论】:

  • 如果你在 infobar.js 中插入外部 iframe 会发生什么,即两级深度?
  • 同样的问题。在inject.js 中,我可以将行frameUrl: chrome.runtime.getURL("src/inject/frame.html") 更改为frameUrl: chrome.runtime.getURL("example.com/page.html") 我看到相同的“拒绝帧”错误。
  • getURL 仅适用于本地页面。对外部站点使用普通的 http url。
  • 你是对的,对不起。我手动输入了该评论。实际代码只是一个字符串 url。

标签: google-chrome-extension content-security-policy


【解决方案1】:

正确的方法是在后台脚本中使用chrome.webRequest API 并拦截 HTTP 响应。

然后您可以覆盖响应标头以修改 Content-Security-Policy 标头。您还可以修改 X-Frame-Options 标头(如果需要)。

文档:chrome.webRequest

【讨论】:

    猜你喜欢
    • 2013-10-12
    • 2012-08-15
    • 2016-10-09
    • 1970-01-01
    • 1970-01-01
    • 2015-02-28
    • 2020-04-28
    • 1970-01-01
    • 2014-12-20
    相关资源
    最近更新 更多