Python Flask应用向客户端传递HTML状态遇转义问题的解决方法咨询
问题根因
当前遇到的转义问题并非JSON序列化逻辑异常,是Flask配套的Jinja2模板引擎的默认安全机制导致:所有通过{{ 变量名 }}插入模板内容的变量,都会被自动转义为HTML实体(比如双引号转成"、尖括号转成<),用于防范XSS攻击。
实际渲染后出现let test = JSON.parse({"test": "<table...的异常,正是这层转义触发的结果:原本正常的JSON字符串经过实体转义后,既不符合JS语法要求,也无法被JSON.parse正常解析。
正确的端到端传输实现方案
方案1:模板层显式关闭自动转义
在前端模板输出变量时,添加Jinja2的safe过滤器,标记该内容为可信内容,跳过自动实体转义:
- 后端逻辑保持原有实现不变,还是通过
json.dumps将字典序列化为JSON字符串传给模板 - 前端接收代码修改为:
这种写法会直接输出后端生成的原始JSON字符串,可被JS正常解析。注意:使用let test = JSON.parse({{ step_table_state | safe }});safe标记的内容需为完全可信的非用户可控内容,否则会引入XSS安全风险。
方案2:使用Flask内置的tojson过滤器(推荐)
这是最安全、最省心的实现方式,不需要手动处理转义逻辑:
- 后端不需要手动调用
json.dumps,直接将原始字典对象传给模板即可:@app.route("report_page", methods=["GET"]) def report_page(): return render_template( "report_input.html", form=form, step_table_state={"test": html_state["step_table_html"]}, ) - 前端模板直接通过
tojson过滤器注入JS变量,不需要额外写JSON.parse:
该过滤器是Flask内置实现,会自动完成Python对象到合法JSON字符串的转换,同时自动做XSS安全转义,不会出现实体转义导致的解析异常,也不存在安全隐患。let test = {{ step_table_state | tojson }};
前端侧还原已转义实体字符串的方法
如果已经拿到了被转义的HTML实体字符串(即实际渲染后满是"、<的内容),无需改动后端逻辑,可通过浏览器内置的DOM解码能力还原:
- 纯JS实现方式:
// 获取当前实际渲染拿到的转义后字符串 const escapedContent = `{"test": "<table class=\\\"table table-striped\\\" id=\\\"stepsTable\\\">...`; // 创建临时DOM元素,利用浏览器的HTML实体自动解码能力还原原始内容 const tempEl = document.createElement('div'); tempEl.innerHTML = escapedContent; const rawJson = tempEl.textContent; // 正常解析JSON即可拿到原始数据 const test = JSON.parse(rawJson); - jQuery实现方式:
const escapedContent = $('script#step-table-state').html(); // 获取转义后的内容 const rawJson = $('<div/>').html(escapedContent).text(); // 完成实体解码 const test = JSON.parse(rawJson);
内容的提问来源于stack exchange,提问作者Mr. Blonde
相关产品推荐
相关产品推荐

