Django模板:仅标记特定HTML标签为安全标签
解决方案:基于白名单的HTML过滤
核心思路是只保留你允许的标签,过滤掉所有其他HTML内容及危险属性,这样既能实现指定标签的原样展示,又能避免XSS攻击。下面分后端(安全首选)和前端场景给出具体实现:
后端处理(安全首选)
用成熟的HTML清理库来做白名单过滤,比如Python生态的bleach,这是很多项目的标配方案:
- 先安装库:
pip install bleach
- 编写过滤函数:
import bleach # 定义你的标签白名单 ALLOWED_TAGS = ['br', 'italic', 'strong', 'ul', 'li'] # 不允许任何标签属性(避免恶意属性如onclick、src等) ALLOWED_ATTRIBUTES = {} def sanitize_user_html(raw_html): # 清理输入,只保留白名单内的标签和属性 cleaned_content = bleach.clean(raw_html, tags=ALLOWED_TAGS, attributes=ALLOWED_ATTRIBUTES) return cleaned_content
- 使用方式:
把用户输入的HTML先经过这个函数处理,再用safe过滤器渲染展示即可。比如在Django模板里:
{{ cleaned_content|safe }}
前端辅助过滤(仅作补充,不能替代后端)
如果是纯前端应用,或者需要即时预览,可以用浏览器的DOMParser来做前端过滤,但记住后端必须再做一次校验,防止恶意用户绕过前端逻辑:
function sanitizeUserHtml(rawInput) { const allowedTags = new Set(['BR', 'ITALIC', 'STRONG', 'UL', 'LI']); const parser = new DOMParser(); const doc = parser.parseFromString(rawInput, 'text/html'); // 遍历所有元素,过滤非法标签和属性 doc.body.querySelectorAll('*').forEach(element => { if (!allowedTags.has(element.tagName)) { // 非法标签替换为纯文本 element.replaceWith(document.createTextNode(element.textContent)); } else { // 移除允许标签的所有属性,避免风险 Array.from(element.attributes).forEach(attr => element.removeAttribute(attr.name)); } }); return doc.body.innerHTML; }
关键注意事项
- 后端过滤是必须的:前端逻辑可以被篡改,后端才是防止XSS的最后防线
- 严格控制白名单:不要轻易添加额外标签或属性,哪怕看起来无害
- 测试边缘场景:比如嵌套标签、恶意脚本标签、带属性的合法标签,确保过滤逻辑能正确处理
内容的提问来源于stack exchange,提问作者OhMad
相关产品推荐
相关产品推荐

