我正在使用谷歌浏览器扩展程序,其中应该包含Facebook的sdk.js,但问题是由于内容安全政策,我无法使该应用程序正常运行。这是其中的一部分我的代码:
的manifest.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>
popup.js
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'"
或&#34; content_security_policy&#34;:"script-src 'self' https://connect.facebook.net/en_US/ 'inline-eval'; object-src 'self'"
但没有运气......我该怎么办?
答案 0 :(得分:2)
Google认为eval是一种不安全的,具有潜在危险的操作,因为动态内容可能会进入应用程序/扩展程序并自行运行,从而可以访问整个强大的Chrome世界。*提供一次访问权限的API通常是对普通网站JavaScript禁止的文件系统和其他资源。
因此,在您的扩展程序和应用中使用这些违反CSP的库的唯一方法是sandbox them:
我们通过将扩展包中的特定HTML文件列为沙盒来实现此目的。每当加载沙盒页面时,它将被移动到唯一的源,并且将被拒绝访问chrome。* API。如果我们通过iframe将这个沙盒页面加载到我们的扩展中,我们可以传递消息,让它以某种方式处理这些消息,并等待它将结果传递给我们。这种简单的消息传递机制为我们提供了在扩展程序的工作流程中安全地包含eval驱动代码所需的一切。
简而言之,您需要在扩展程序中创建一个额外的组件,一个沙盒的HTML文件,并加载有问题的Facebook代码。然后,您将在沙盒页面中添加侦听器,该侦听器可以从包含HTML页面接收消息,然后处理扩展中的事件。这可以保护您的用户免受评估,因为评估代码无法访问沙盒中的任何Chrome API。
当我使用sipml5的JavaScript SIP库时,我遇到了同样的问题。该库使用eval非常自由,因此使用该库的唯一方法是在沙箱中。我创建了一个小型库,用于处理沙盒和主应用程序之间的同步存储数据,称为Sandbox StorageAPI for Chrome™。在代码中,您可以看到我在沙盒和主页之间的通信方式:
<强>的manifest.json:强>
"sandbox": {
"pages": ["sandbox.html" ]
},
<强> mainpage.html:强>
<!-- Sandboxed page -->
<iframe height="800" width="1200" id="sandboxFrame" class="sandbox active" src="sandbox.html" style=""></iframe>
<强> storageAPI.js:强>
在这里,我在沙盒中创建一个侦听器,用于侦听app / extension的主要安全部分,以便使用沙箱“注册”自身,然后存储该引用,以便沙箱可以与主模块进行通信: / p>
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。你真的只需要它就可以运行不安全的代码。
免责声明:我是Chrome™开发人员的Sandbox StorageAPI。我不隶属于Google或Chrome,并且所有商标均属于Google。