Underscore.js的_.template在Chrome扩展程序中引发错误

17
如果我在Google Chrome扩展程序中使用underscore.js_.template(),则会在控制台中收到以下错误消息:

未捕获的错误:不允许从字符串生成代码

有没有办法解决这个错误?


您可能还会看到“由于内容安全策略而拒绝执行内联脚本”的提示。 - Stefano
X-WebKit-CSP: script-src 'unsafe-eval'; - user956584
6个回答

7
感谢Chromium列表的贡献者指出,以underscore的方式创建Function对象需要在manifest.json选项中包含'unsafe-eval'的content_security_policy
例如,你的manifest.json可以是:
{
  "manifest_version": 2,
  ...
  "content_security_policy": "script-src 'self' 'unsafe-eval'",
  ...
}

然后下划线的行为将起作用,因为此策略允许它。有关格式的更多信息,请参阅此选项的Chrome文档这里


1
链接已经失效了,我不知道如何添加'unsafe-eval',Chromium一直在拒绝我尝试的所有方法。你可以在回答中添加一个例子吗?谢谢。 - Jorge Vargas
2
这是一个添加 unsafe-eval 到 manifest.json 的例子:https://github.com/djmccormick/linkswapp-chrome/blob/master/manifest.json - djmccormick
3
谢谢,我还发现在Chrome扩展版本2中,unsafe-eval目前无法使用。这里正在讨论接受unsafe-eval或禁用它的问题(当前问题状态是wontfix):http://code.google.com/p/chromium/issues/detail?id=107538 - Jorge Vargas
无法从'/home/Envs/todolist'加载扩展程序。'content_security_policy'的值无效。我一直在收到上述错误。 - user993563
我已创建了一个超级基本的示例,演示如何完成这个操作:https://github.com/djmccormick/content-security-policy-test - djmccormick
这在清单版本2上不起作用。请参考@AndrewBrown的答案。 - djmccormick

5

很遗憾,我认为您无法在chrome扩展内使用underscore.js的_.template()函数, 至少在新的manifest.json版本2中不行。同样适用于尝试使用jQuery模板插件

来自Google Chrome扩展的内容安全策略页面:

没有放松执行内联JavaScript限制的机制。特别地,设置包括unsafe-inline的脚本策略将没有任何效果。这是有意为之的。

我将寻找其他模板引擎,希望它们不会使用new Function对象。


内联脚本限制仅适用于出现在HTML页面内部的JS(即“内联”JS)。您可以通过将先前内联的JS放入自己的.js文件中,并通过脚本标记或通过其他机制加载它来绕过上面引用的特定内容。换句话说,您引用的内容似乎不适用于不安全的eval问题。 - jefflunt

4

我使用 Underscore.js 是因为我想要在我的 Chrome 插件中使用 Backbone.js,我只是把模板引擎改成了 Mustache。如果你有同样的理由,你也可以在 Backbone 中使用 Underscore.js,但是不要使用 _.template() 函数。


使用Mustache而不是Underscore的_.template对我来说是最简单的解决方案。 - Kevin Jantzer
是的,Mustache 可以 +1 - Kirzilla

0

链接已失效。 - Paul Heil

0
你可以使用jQuery的$('<element .../>')结构编写自己的模板迷你引擎。
简洁的方法:
function myElement(text) {
  var d = $('<div class="abc"/>');
  d.text(text);
  return d;
}

myElement('my text').appendTo(domParent);

一种不太优雅的方法:

var yourTemplate = '<div>${somevar}</div>';

function instTemplate(tmpl, text) {
  return $(tmpl.replace(/\$\{somevar\}/g, text));
}

instTemplate(yourTemplate, 'your text').appendTo(domParent);

例如,如果您知道替换数据不会有害等情况,使用简单的jquery.tmpl模板重写是相当快速的,但这种方法可能不太规范。


0

如上所述,清单v2的限制禁止使用Eval、new Function和内联脚本 - 即使在与内容安全策略相互作用时也无法放松此安全策略

大多数模板库在某个时候都会使用evals。 一种解决方案是重写您的扩展,以便所有逻辑都驻留在JavaScript中,而模板中没有任何东西; 在这种情况下,Google jstemplate等解决方案应该可用。

然而,有一个选项可以在sandboxed iframe内执行Eval和new Function,例如在清单中使用以下几行:

"sandbox": {
    "pages": [
      "page1.html",
      "directory/page2.html"
    ]
},

沙盒页面将无法访问扩展或应用程序API,也无法直接访问非沙盒页面(可以通过postMessage()与它们通信)。您可以使用特定的CSP进一步限制沙盒权限

现在,Google Chrome团队有一个完整的示例github eval in iframe,介绍如何通过与沙盒iframe通信来规避问题,以及短分析教程

希望会有一些库使用这种机制来提供与标准模板使用的完全兼容性,尽管出于性能原因,我建议从模板中删除尽可能多的逻辑...

感谢Google,有很多扩展需要重写 :(


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接