Flask渲染模板时如何让传入变量内的HTML标签正常解析生效?
问题原因
Flask 搭载的 Jinja2 模板引擎默认开启自动转义机制:所有通过 {{ }} 语法传入的动态变量,其中的 <、> 这类HTML特殊字符会被转义为字符实体,最终以纯文本形式展示,从根源上避免不可信内容造成XSS注入攻击。
你模板里写死的 <h1> 属于静态模板内容,不会触发转义,所以能正常渲染;动态传入的 update_list[0] 里的 <p> 标签被转义,才会显示为纯文本。
解决方法
根据你的使用场景选以下任意一种即可,所有方法的前提都是你要渲染的HTML内容完全可信,不存在用户提交的恶意脚本,否则会引发安全问题。
- 方法1:模板中给单个变量加
safe过滤器(最常用,粒度最细)
直接修改ticket.html的变量输出语法,告诉Jinja2这个内容是安全的,不需要转义:
如果要渲染整个列表,遍历的时候给每个变量加<h1> {{ update_list[0] | safe }} </h1>safe即可。 - 方法2:后端标记内容为安全HTML
如果不想在模板里逐个加过滤器,可以在后端用Flask自带的Markup类把需要渲染的HTML内容标记为安全,传入模板后会直接渲染:
这种方式不需要修改模板代码,原来的from flask import Flask, render_template, Markup @app.route("/ticket/<int:ticket_id>") def ticket(ticket_id): update_list = get_data(ticket_id) # 将列表中每一项标记为可直接渲染的安全HTML safe_update_list = [Markup(content) for content in update_list] return render_template('ticket.html', ticket_id=ticket_id, update_list=safe_update_list){{ update_list[0] }}写法就能正常解析HTML标签。 - 方法3:模板局部关闭自动转义
如果某一个模板块里的所有动态变量都需要渲染HTML,可以用autoescape标签临时关闭转义:{% autoescape false %} <h1> {{ update_list[0] }} </h1> <!-- 这个块内的所有动态变量都不会被转义 --> {% endautoescape %}
注意:绝对不要对用户可提交、未经过滤的内容关闭转义或者加safe标记,否则恶意用户可以注入
<script>标签执行任意JS代码,窃取用户数据、篡改页面内容。
内容的提问来源于stack exchange,提问作者Jankes
相关产品推荐
相关产品推荐

