如何使用Nunjucks安全地将JSON呈现为内联<script>?

时间:2017-09-26 12:16:20

标签: javascript html json nunjucks

我们有一个服务器端呈现的HTML页面,其中包含一个外部JavaScript文件。要触发该文件中的代码,我们要调用一个函数并传递一些动态数据(以JSON的形式):

&#xA;&#xA;
 &lt; script src = “/静态/富/ bar.js” &GT;&LT; /脚本&GT;&#XA;&LT;脚本&GT;&#XA; foo.bar.init({biz:42,qux:“quux”});&#xA;&lt; / script&gt;&#xA;  
&#xA;&#xA;

我们从Nunjucks模板渲染它,并在上下文中将JSON对象作为值 data 传递。这可以包含任意数据,包括用户提供的内容。

&#xA;&#xA;

这是安全的但不起作用,因为&lt;&gt;&amp; 是被转义(感谢Nunjucks autoescaping):

&#xA;&#xA;
  foo.bar.init({{data | dump}});&#xA;  
&#xA;&#xA;

这有效,但不安全,因为JSON中的字符串可能包含文本&lt; / script&gt;

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

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

&#xA;

1 个答案:

答案 0 :(得分:2)

暂时这样做:

  /**
   * 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>

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