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

Django+Ajax实时聊天表单的安全风险排查及优化咨询

实时聊天页面的安全注意事项及代码修复

需注意的其他安全问题

  • 输入验证与XSS防护:Django Forms自带的验证和转义逻辑很重要,原生JS提交时必须在后端补全——不仅要校验消息长度、非空,还要对内容做HTML标签清洗,防止恶意脚本注入页面。前端渲染消息时也要用textContent而非innerHTML,避免解析恶意标签。
  • 身份与权限校验:必须确保请求来自已登录用户,且该用户是当前聊天会话的合法参与者。后端要严格校验请求中的聊天室ID与用户权限匹配,不能仅依赖前端隐藏字段的限制。
  • 请求频率限制:防止恶意用户发送垃圾消息,可通过Django的django-ratelimit或自定义中间件,限制单位时间内的消息发送次数。
  • 数据传输加密:生产环境强制使用HTTPS,避免聊天内容在传输过程中被窃听。
  • 后端逻辑兜底:前端的验证只能做基础拦截,后端必须对所有参数做二次校验,比如防止用户篡改请求中的聊天室ID、发送者ID等参数。

修复后的代码示例

前端原生JS提交代码

// 获取CSRF令牌
function getCookie(name) {
    let cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        const cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i++) {
            const cookie = cookies[i].trim();
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

// 发送消息函数
function sendMessage() {
    const input = document.getElementById('message-input');
    const content = input.value.trim();
    const roomId = document.getElementById('chat-room-id').value;

    // 前端基础校验
    if (!content || content.length > 500) {
        alert('消息不能为空且长度不能超过500字符');
        return;
    }

    const csrftoken = getCookie('csrftoken');
    fetch('/chat/send/', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'X-CSRFToken': csrftoken
        },
        body: JSON.stringify({
            'content': content,
            'chat_room_id': roomId
        })
    })
    .then(res => res.json())
    .then(data => {
        if (data.success) {
            // 安全渲染消息:用textContent避免XSS
            const msgContainer = document.getElementById('messages');
            const newMsg = document.createElement('div');
            newMsg.className = 'user-msg';
            newMsg.textContent = data.content;
            msgContainer.appendChild(newMsg);
            input.value = '';
        } else {
            alert(data.error || '发送失败');
        }
    })
    .catch(err => {
        console.error('发送错误:', err);
        alert('发送出错,请重试');
    });
}

后端Django视图代码

from django.http import JsonResponse
from django.contrib.auth.decorators import login_required
from django.utils.html import escape
from .models import ChatRoom, Message
import bleach

@login_required
def send_message(request):
    if request.method != 'POST':
        return JsonResponse({'success': False, 'error': '仅支持POST请求'}, status=405)
    
    try:
        data = request.json()
        content = data.get('content', '').strip()
        room_id = data.get('chat_room_id')

        # 后端参数校验
        if not content or len(content) > 500:
            return JsonResponse({'success': False, 'error': '消息内容无效'}, status=400)
        
        # 验证用户是否有权访问该聊天室
        try:
            chat_room = ChatRoom.objects.get(id=room_id)
            if request.user not in chat_room.participants.all():
                return JsonResponse({'success': False, 'error': '无权限发送消息'}, status=403)
        except ChatRoom.DoesNotExist:
            return JsonResponse({'success': False, 'error': '聊天室不存在'}, status=404)
        
        # 清洗内容,彻底防止XSS
        cleaned_content = bleach.clean(content, tags=[], attributes={}, strip=True)
        # 若不需要bleach,也可使用Django自带的escape:cleaned_content = escape(content)

        # 创建消息记录
        Message.objects.create(
            sender=request.user,
            chat_room=chat_room,
            content=cleaned_content
        )

        return JsonResponse({
            'success': True,
            'content': cleaned_content,
            'sender': request.user.username,
            'time': Message.objects.latest('id').timestamp.strftime('%H:%M')
        })
    
    except Exception as e:
        return JsonResponse({'success': False, 'error': '服务器内部错误'}, status=500)

额外说明

  • 需安装django-bleach以实现更严格的内容清洗:pip install django-bleach
  • 前端渲染消息时务必使用textContent,禁止直接插入HTML
  • 可添加django-ratelimit对send_message视图做频率限制,比如每分钟最多发送10条消息

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 10:00:23