Jinja2与Flask的HTML自动转义

今天写一个页面的时候发现代码竟然原封不动的出现了,怀疑是Jinja的自动转义。结果发现Jinja2的Escaping是自动关闭的,下面是Jinja官方文档中描述的,默认自动转义是关闭的,可以手动转义或者开启自动转义。

HTML Escaping

When generating HTML from templates, there’s always a risk that a
variable will include characters that affect the resulting HTML. There
are two approaches: manually escaping each variable or automatically
escaping everything by default.

Jinja supports both, but what is used depends on the application
configuration. The default configuaration is no automatic escaping for
various reasons:

escaping everything except of safe values will also mean that Jinja is
escaping variables known to not include HTML such as numbers which is
a huge performance hit. The information about the safety of a variable
is very fragile. It could happen that by coercing safe and unsafe
values the return value is double escaped HTML.

转而搜索发现是Flask的原因,Flask的自动转义是默认开启的,如需要关闭需要以下操作(来自官方文档):

自动转义就是自动帮你将特殊的字符替换成转义符号。HTML(或者XML, XHTML)的特殊字符有 &, >, <, “, ‘ 。因为这些字符在文档中有它自己特殊的含义,所以如果你想在文章中使用这些符号,必须将它替换成转义符号。如果不这样做,不仅用户使用不了这些符号,还会导致安全问题。(更多 :ref:xss)

但是有时候你需要在模版中禁用自动转义。如果你想直接将HTML插入页面,比如将markdown语言转换成HTML,那么你就需要这样做了。

有3种方法可以关闭自动转义:

  • 在Python文件中进行转义。先在 :class:~flask.Markup 对象中进行转义,然后将它传送给模版。一般推荐使用这个方式。
  • 在模版文件中进行转义。通过 |safe 过滤器来表示字符串是安全的()
  • 暂时禁用全局的自动转义功能。

要想在模版中禁用全局自动转义功能,可以用 语句块:
{\% codeblock lang:python \%}
{\% autoescaping false \%}
autoescaping is disableed here
{\% endautoescape \%}
{\% endcodeblock \%}

在这么做的时候,要语句块中使用到的变量非常小心。

自动开始转义也是不错的,这方面的安全就可以少考虑了,关闭也很简单。我直接使用第二种方式,在需要禁止转义的部分加上safe标记,很方便。其他的两种目前还没用上~