You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django如何安全将用户表单输入的@标识转换为链接渲染,规避XSS风险

实现方案

核心逻辑:不要将拼接好的HTML内容存入数据库,保留用户原始纯文本输入,渲染阶段先做HTML转义再替换@提及为链接,从根源避免XSS注入风险。

步骤1:创建自定义模板过滤器

在你的posts应用目录下新建templatetags文件夹,文件夹内新增两个文件:

  • 空文件__init__.py,用于标识该目录为Python包
  • post_filters.py,写入过滤器逻辑:
from django import template
from django.utils.html import escape, mark_safe
import re

register = template.Library()

@register.filter
def mention_link(content):
    # 先转义所有用户输入内容,将HTML标签转为纯文本实体,避免XSS
    escaped_content = escape(content)
    # 正则匹配@后合法标识,可根据业务需求调整允许的字符,如需支持中文可添加\u4e00-\u9fa5
    pattern = r'@([a-zA-Z0-9_]{1,20})'
    
    def replace_mention(match):
        page_name = match.group(1)
        # 站内链接可根据实际路由规则调整,参数额外转义避免路径注入
        return f'<a href="/page/{escape(page_name)}">@{escape(page_name)}</a>'
    
    processed_content = re.sub(pattern, replace_mention, escaped_content)
    # 仅经过安全处理的内容标记为可安全渲染
    return mark_safe(processed_content)

新增过滤器后需要重启Django服务生效。

步骤2:修改模板文件

修改page.html,首先在文件最顶部加载自定义过滤器,再替换帖子内容的渲染逻辑:

<!-- 顶部新增加载过滤器 -->
{% load post_filters %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Testing</title>
</head>
<body>
    <form method="post" enctype="multipart/form-data">
        {% csrf_token %}
            {{ post_form }}
            <button class="btn btn-primary my-4" type="submit">Submit</button>
      </form>
      {% for post in posts %}
      <p>{{post.id}}</p>
      <!-- 替换原内容渲染,使用自定义过滤器 -->
      <p>{{post.post|mention_link}}</p>
      {% endfor %}
</body>
</html>

方案优势

  1. 数据库存储原始纯文本,后续如果调整链接规则不需要批量修改存量数据
  2. 完全规避XSS风险:所有用户输入的恶意HTML都会被转义为纯文本展示,仅我们可控的@提及会被替换为安全链接

内容的提问来源于stack exchange,提问作者Adam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 02:18:01