如何在使用Nunjucks时安全地将JSON渲染为内联<script>?

8
我们有一个服务器端渲染的 HTML 页面,其中包含外部 JavaScript 文件。为了触发该文件中的代码,我们希望调用一个函数并将一些动态数据(以 JSON 形式)传递给它:
<script src="/static/foo/bar.js"></script>
<script>
  foo.bar.init({biz: 42, qux: "quux"});
</script>

我们正在使用Nunjucks模板进行渲染,并将JSON对象作为上下文中的值data传递。这可以包含任意数据,包括用户提供的内容。
这是安全的,但不起作用,因为<>&被转义了(感谢Nunjucks自动转义)。
foo.bar.init({{ data | dump }});

这个方法可以运行,但是不安全,因为JSON字符串中可能包含文本</script>

foo.bar.init({{ data | dump | safe }});

如何说服Nunjucks渲染这个JSON,以便可以安全且正确地解释它?听起来应该是一个已经解决的问题,但我无法在任何地方找到现成的解决方案。
1个回答

7

现在先这样做:

  /**
   * Returns a JSON stringified version of the value, safe for inclusion in an
   * inline <script> tag. The optional argument 'spaces' can be used for
   * pretty-printing.
   *
   * Output is NOT safe for inclusion in HTML! If that's what you need, use the
   * built-in 'dump' filter instead.
   */
  env.addFilter('json', function (value, spaces) {
    if (value instanceof nunjucks.runtime.SafeString) {
      value = value.toString()
    }
    const jsonString = JSON.stringify(value, null, spaces).replace(/</g, '\\u003c')
    return nunjucks.runtime.markSafe(jsonString)
  })

使用方法:

<script src="/static/foo/bar.js"></script>
<script>
  foo.bar.init({{ data | json }});
</script>

更好的解决方案仍然欢迎。

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