在Django模板中安全地使用JSON和JSON内部的JSON

spe*_*ane 8 html javascript python django

你如何在django webapp中安全地呈现JSON数据?

在django的服务器上,我生成JSON数据,然后在django模板中呈现该JSON数据.JSON偶尔会包含html的片段.大多数情况下,这很好,但是如果</script>标记在渲染时在JSON数据中,它会破坏周围的javascript.

例如...

在服务器上,在python我会有这个:

template_data = {
    'my_json' : '[{"my_snippet": "<b>Happy HTML</b>"}]'
}
# pass the template data to the django template
return render_to_response('my_template.html', template_data, context_instance = c)
Run Code Online (Sandbox Code Playgroud)

然后在模板中:

<script type="text/javascript">
var the_json = {{my_json|safe}};
</script>
... some html ...
Run Code Online (Sandbox Code Playgroud)

生成的HTML工作得很好,看起来像这样:

<script type="text/javascript">
var the_json = [{"my_snippet": "<b>Happy HTML</b>"}];
</script>
... some html ...
Run Code Online (Sandbox Code Playgroud)

但是,当在服务器上,JSON看起来像这样时,会遇到问题:

template_data = {
    'my_json' : '[{"my_snippet": "Bad HTML</script>"}]'
}
return render_to_response('my_template.html', template_data, context_instance = c)
Run Code Online (Sandbox Code Playgroud)

现在,当它被渲染时,你会得到:

<script type="text/javascript">
var the_json = [{"my_snippet": "Bad HTML</script>"}];
</script>
... some html ...
Run Code Online (Sandbox Code Playgroud)

JSON代码中的结束脚本标记被视为关闭整个脚本块.然后你的所有javascript都会破解.

一种可能的解决方案是检查</script>何时将模板数据传递给模板,但我觉得有更好的方法.

Fla*_*ash 15

安全地将JSON作为字符串插入,然后在其上调用JSON.parse

使用escapejs而不是安全.它专为输出到JavaScript而设计.

var the_json = '{{my_json|escapejs}}';
Run Code Online (Sandbox Code Playgroud)

要获取JavaScript对象,您需要调用JSON.parse该字符串.出于安全原因,这总是比将JSON编码转储到脚本并直接评估它更好.

一个有用的过滤器将python对象直接发送到我使用的客户端是这样的:

@register.filter
def to_js(value):
    """
    To use a python variable in JS, we call json.dumps to serialize as JSON server-side and reconstruct using
    JSON.parse. The serialized string must be escaped appropriately before dumping into the client-side code.
    """
    # separators is passed to remove whitespace in output
    return mark_safe('JSON.parse("%s")' % escapejs(json.dumps(value, separators=(',', ':'))))
Run Code Online (Sandbox Code Playgroud)

并使用它像:

var Settings = {{ js_settings|to_js }};
Run Code Online (Sandbox Code Playgroud)