‘
cleaned = bleach.clean(unsafe_html, tags=allowed_tags)
结果:
欢迎访问 官网
<marquee>滚动文字</marquee>
### 精细化控制属性白名单仅限制标签是不够的,属性同样是 XSS 的高发区,Bleach 允许通过 `attributes` 参数为每个标签单独配置允许的属性。- 简单列表形式:所有允许标签共享同一组属性。- 字典形式:为不同标签定义不同的属性集(推荐)。```pythonimport bleach# 为不同标签配置不同属性allowed_attrs = { 'a': ['href', 'title', 'rel'], 'img': ['src', 'alt', 'width', 'height'],}unsafe_html = '<a href="http://safe.com" onclick="steal()">链接</a><img src="pic.jpg" onload="hack()">'cleaned = bleach.clean(unsafe_html, tags=['a', 'img'], attributes=allowed_attrs)# 结果:<a href="http://safe.com">链接</a><img src="pic.jpg">协议过滤与链接转换
Bleach 还能过滤 href 或 src 中的协议,防止 javascript:alert(1) 这种伪协议攻击。
- 协议白名单:通过
protocols参数指定,默认允许http,https,mailto。 - 自动链接化:使用
bleach.linkify()将文本中的 URL 自动转换为<a>
import bleach text = "请访问 https://google.com 查看详情" linked_text = bleach.linkify(text) # 结果:请访问 <a href="https://google.com" rel="nofollow">https://google.com</a> 查看详情
bleach python 与 html.escape 区别
很多开发者在初学时会混淆 bleach.clean()
和 Python 标准库中的 html.escape(),虽然两者都涉及 HTML 处理,但其设计目标和应用场景截然不同。
核心差异对比
| 维度 | html.escape | bleach.clean |
|---|---|---|
| 处理逻辑 | 全量转义(Escaping) | 选择性清洗(Sanitizing) |
| 结果形式 | 将 < 变为 <,所有 HTML 失效 |
保留安全标签,剔除/转义危险部分 |
| 适用场景 | 显示用户原样输入的文本 | 渲染经过审核的富文本/HTML 内容 |
| 性能开销 | 极低(简单的字符串替换) | 较高(需要解析 DOM 树) |
| 安全性 | 绝对安全(因为不渲染任何 HTML) | 高度安全(基于白名单过滤) |
场景选择指南
- 场景 A:用户评论区,如果要求用户只能输入纯文本,请直接使用
html.escape(),这样无论用户输入什么,页面都会将其视为文字显示,不会被浏览器执行。 - 场景 B:博客编辑器/CMS 系统,如果允许用户使用加粗、斜体、插入图片,则必须使用
,它能在保证页面布局不被破坏的前提下,剔除恶意脚本。bleach.clean()
行业共识认为,安全防御应采取分层策略,在存储阶段可以使用 Bleach 进行初步清洗,在渲染阶段根据上下文选择合适的转义方法,构建深度防御体系。
Django 项目中使用 bleach 库的性能
在高性能的 Web 应用中,尤其是使用 Django 或 Flask 等框架时,频繁调用 Bleach 的解析过程可能会成为性能瓶颈,因为 Bleach 依赖的 html5lib 在解析大型 HTML 文档时速度相对较慢。
性能优化策略
为了在保证安全的同时不牺牲响应速度,可以采取以下优化方案:
- 清洗时机前移:不要在每次页面渲染(Template 渲染)时调用
bleach.clean(),应该在数据写入数据库之前(如在 Django Model 的save()方法或 Form 的clean()方法中)进行一次性清洗。 - 结果缓存:对于不经常变动的富文本内容,将清洗后的 HTML 结果缓存到 Redis 中,避免重复解析。
- 限制输入长度:在调用 Bleach 之前,先对输入字符串进行长度截断,处理 10KB 的 HTML 和处理 1MB 的 HTML 在性能上有着量级差别。
实际集成路径
在 Django 中,最优雅的集成方式是自定义模板过滤器(Template Filter):
- 在 app 目录下创建
templatetags文件夹。 - 编写过滤器代码:
from django import template
import bleach
register = template.Library()
@register.filter(name='safe_html')
def safe_html(value):
# 定义业务所需的白名单
allowed_tags = ['b', 'i', 'u', 'p', 'br']
return bleach.clean(value, tags=allowed_tags)
- 在模板中使用:
{{ content|safe_html|safe }},注意,|safe是 Django 的内置过滤器,告诉模板引擎不要再次转义 Bleach 已经清洗过的安全标签。
Bleach 为 Python 开发者提供了一种结构化、可配置的 HTML 清洗方案,通过白名单机制有效解决了 XSS 攻击这一核心痛点,在实际应用中,应根据业务需求精准配置标签和属性白名单,并结合 html.escape 实现分层防御,同时通过前置清洗和缓存来抵消解析性能的损耗。
Bleach Python 相关常见问题 Q&A
Bleach 库目前是否还在维护?
Bleach 依然是 Python 社区处理 HTML 清洗的主流选择,虽然更新频率有所降低,但其基于 html5lib 的解析逻辑依然稳健,对于绝大多数 Web 应用的 XSS 防御需求,它提供的功能已经足够且成熟。
Bleach 能处理 SVG 标签中的恶意代码吗?
SVG 标签非常复杂,内部可以包含 <script> 或 onload 事件,如果将 svg 加入白名单,必须极其谨慎地配置其允许的属性,据统计,许多 XSS 漏洞正是通过允许 SVG 标签但未严格限制属性而产生的,建议除非必要,否则不要在白名单中开启 svg
如果我想完全删除非法标签而不是转义它们该怎么做?
在调用 bleach.clean() 时,可以通过设置 strip=True 参数来实现,默认情况下,Bleach 会将非法标签转义为 <tag> 形式显示在页面上;设置 strip=True 后,非法标签及其内容将被直接从字符串中删除。
首发原创文章,作者:世雄 - 原生数据库架构专家,如若转载,请注明出处:https://idctop.com/article/488172.html



