javascript - 谷歌浏览器扩展内容安全政策

标签 javascript json facebook google-chrome google-chrome-extension

我正在开发一个应该包含 Facebook 的 sdk.js 的 Google Chrome 扩展程序,但问题是由于内容安全策略,我无法使该应用程序运行。这是我的部分代码:

list .json

{
  "manifest_version": 2,

  "name": "<app-name>",
  "description": "<description>",
  "version": "0.1",

  "permissions": [
  "tabs","<all_urls>"
  ],
  "content_scripts": [
  {
    "matches": [
    "http://*/*",
    "https://*/*"
    ],
    "js": ["intercept_connections.js"]
  }
  ],
  "content_security_policy": "script-src 'self' https://connect.facebook.net/en_US/ 'unsafe-eval'; object-src 'self'",
  "background": {
    "scripts" : ["background.js"]
    },
    "browser_action": {
      "default_icon": "icon.png",
      "default_popup": "popup.html"
    }
  }

popup.html

<html>
<head>
    <title>Facebook Mass Sharer</title>


    <script type="text/javascript" src="popup.js"></script>
    <script type="text/javascript" src="FbApi.js"></script>
</head>

<body>
<body>
    <h1>Post to Facebook</h1>
    <button id="postTest">TestMe</button>

  </body>
</body>
</html>

弹出窗口

var handleClick = function() {
    postToGroup(<groupID>);
}

var initialize = function() {
    var test = document.getElementById('postTest');
    test.addEventListener("click",handleClick);
}

window.addEventListener("load", initialize);

FbApi.js(我做的)

window.onload = function() {
    window.fbAsyncInit = function() {
        FB.init({
          appId      : '<appID>',
          xfbml      : true,
          version    : 'v2.1',
          oauth      : true
        });
      };

      (function(d, s, id){
         var js, fjs = d.getElementsByTagName(s)[0];
         if (d.getElementById(id)) {return;}
         js = d.createElement(s); js.id = id;
         js.src = "https://connect.facebook.net/en_US/sdk.js";
         fjs.parentNode.insertBefore(js, fjs);
       }(document, 'script', 'facebook-jssdk'));
}

var postToGroup = function(groupID) {
    FB.api(
    "/"+groupID+"/feed",
    "POST",
    {
        "message": "This is a test message"
    },
    function (response) {
      if (response && !response.error) {
        /* handle the result */
      }
    }
);
}

问题是我一直收到这个错误:

Refused to execute JavaScript URL because it violates the following Content Security Policy directive: "script-src https:// 'unsafe-eval'". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution.

我尝试更改 "content_security_policy": "script-src 'self' https://connect.facebook.net/en_US/'unsafe-eval'; object-src 'self'""content_security_policy": "script-src 'self'; object-src 'self'" 或 "content_security_policy": "script-src 'self' https://connect.facebook.net/en_US/'inline-eval'; object-src 'self'" 如错误中所建议但没有运气..我应该尝试什么?

最佳答案

Google 认为 eval 是一种不安全的、有潜在危险的操作,因为动态内容可能会进入应用程序/扩展程序并自行运行,从而获得对整个强大 chrome 世界的访问权限。* 提供访问权限的 API到文件系统和其他资源,这些资源通常是普通网站 JavaScript 禁止访问的。

因此,在您的扩展程序和应用程序中使用这些违反 CSP 的库的唯一方法是 sandbox them :

We accomplish this by listing specific HTML files inside the extension package as being sandboxed. Whenever a sandboxed page is loaded, it will be moved to a unique origin, and will be denied access to chrome.* APIs. If we load this sandboxed page into our extension via an iframe, we can pass it messages, let it act upon those messages in some way, and wait for it to pass us back a result. This simple messaging mechanism gives us everything we need to safely include eval-driven code in our extension's workflow.

简而言之,您需要在您的扩展程序中创建一个额外的组件,一个 HTML 文件,您将其沙盒化并加载有问题的 Facebook 代码。然后,您将在沙盒页面中添加监听器,这些监听器可以从包含的 HTML 页面接收消息,然后处理扩展中的事件。这可以保护您的用户免受评估,因为评估代码无法访问沙盒中的任何 Chrome API。

当我使用 sipml5 的 JavaScript SIP 库时,我遇到了同样的问题。该库非常自由地使用 eval,因此使用该库的唯一方法是在沙箱中。我创建了一个小库来处理沙箱和主应用程序之间的同步存储数据,称为 Sandbox StorageAPI for Chrome™ .在代码中,您可以看到我是如何在沙箱和主页之间进行通信的:

list .json:

"sandbox": {
    "pages": ["sandbox.html" ]
  },

ma​​inpage.html:

<!-- Sandboxed page -->
    <iframe height="800" width="1200" id="sandboxFrame" class="sandbox active" src="sandbox.html" style=""></iframe>

storageAPI.js:

在这里,我在沙箱中创建了一个监听器,用于监听应用程序/扩展的主要安全部分以向沙箱“注册”自身,然后存储该引用,以便沙箱可以与主模块通信:

window.addEventListener('message', function(event) {
            console.info("Message received from wrapper = " + JSON.stringify(event.data));
            console.info("location = " + window.location.href);
            switch(event.data.command) {

                case 'initStorageAPI':
                    storageAPI.storage = event.data.storage;  result = "It's alive!!!";
                    storageAPI.sandbox.window.onload();
                    console.info("Prepare to postMessage back to the wrapper...");
                    storageAPI.wrapper = event;
                    event.source.postMessage({'command':'initStorageComplete','result': result}, event.origin);

下面是我们将数据发送回主模块的示例:

storageAPI.setItem = function(key, value) {
        if(storageAPI.CHROME_EXTENSION == false) {
            return window.localStorage.setItem(key, value);
        } else {
            storageAPI.storage[key] = value;
            // send back to the wrapper to store
            storageAPI.wrapper.source.postMessage({'command':'writeStorage', 'storage': storageAPI.storage}, storageAPI.wrapper.origin);

        }

    };

总而言之,您可以使用类似的技术将数据从沙箱来回编码到主模块,将不安全的库与扩展的安全敏感部分连接起来。有关详细信息,请参阅文档。

请记住,iframe 甚至可以 Conceal 。你真的只需要它来运行不安全的代码。

免责声明:我是 Sandbox StorageAPI for Chrome™ 开发人员。我不隶属于 Google 或 Chrome,所有商标均属于 Google。

关于javascript - 谷歌浏览器扩展内容安全政策,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25596026/

相关文章:

javascript - 小部件的预填充字段

JavaScript 创建对象结构数组

java - 如何仅对 Java 对象或 JSON 负载中的某些字段执行特定操作

javascript - 如何将根页面重定向到angularjs中的另一个url

javascript - 获取给定文本的复选框的状态

javascript - AngularJS:上传图像并保存在本地存储中

c# - 在 javascript 中使用 c# 类对象

facebook - 从 Facebook Graph API 检索默认图像所有 URL 个人资料图片

javascript - 通过网站链接在第三方 Facebook 墙上发表评论

javascript - 考虑到新的 Graph API 限制,如何获取用于测试应用程序的 Facebook 好友列表?