当前位置:首页 > 技术 > 正文内容

Django 中的 CSRF 防护机制详解

访客 技术 2026年6月13日 1

CSRF 攻击的基本概念

CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种常见的安全漏洞,攻击者利用用户已登录的身份,在其不知情的情况下发送恶意请求。这种攻击依赖于浏览器自动携带目标站点 Cookie 的特性,从而让服务器误认为请求来自合法用户。

攻击流程分析

  1. 用户登录网站 A,服务器验证通过后设置会话 Cookie,浏览器保存该凭证。
  2. 用户在未退出网站 A 的情况下访问恶意网站 B。
  3. 网站 B 包含一个指向网站 A 的隐藏表单或 AJAX 请求,例如发起转账、修改密码等操作。
  4. 当请求被触发时,浏览器自动附加网站 A 的 Cookie,使服务器认为这是合法操作。
  5. 服务器根据当前会话权限执行敏感操作,导致数据被篡改或账户被盗用。

防御原理:Token 校验机制

为防止此类攻击,Django 使用基于随机 Token 的防护策略:

  • 服务器生成一个难以预测的加密字符串(CSRF Token),并将其嵌入响应页面中(如隐藏字段)。
  • 同时将该 Token 存储在用户的 Cookie 中。
  • 当用户提交 POST 请求时,必须同时提供表单中的 Token 和 Cookie 中的 Token。
  • 服务器比对两者是否一致,只有匹配才允许处理请求。

由于同源策略限制,外部站点无法读取目标站点的 Cookie 或获取动态生成的 Token,因此无法构造有效的请求。

Django 内置的 CSRF 中间件

Django 默认启用了 django.middleware.csrf.CsrfViewMiddleware,位于 MIDDLEWARE 配置项中。该中间件自动为所有适用的视图添加保护逻辑。

全局启用与局部控制

全局防护由中间件统一管理,开发者也可通过装饰器对特定视图进行细粒度控制:

from django.views.decorators.csrf import csrf_exempt, csrf_protect
  • csrf_exempt:豁免某个视图的 CSRF 检查,适用于无需身份验证的接口(如第三方回调)。
  • csrf_protect:强制对该视图启用检查,即使全局未开启中间件也生效。

函数视图中的使用方式

from django.http import HttpResponse
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')
    elif request.method == 'POST':
        # 处理登录逻辑
        return HttpResponse('登录成功')

类视图中的配置方法

对于基于类的视图(Class-Based View),需结合 method_decorator 使用:

from django.utils.decorators import method_decorator
from django.views.generic import TemplateView
from django.views.decorators.csrf import csrf_exempt

@method_decorator(csrf_exempt, name='dispatch')
class LoginView(TemplateView):
    template_name = 'login.html'

    def post(self, request):
        return HttpResponse('支持 POST 请求')

或者直接在 URL 路由中装饰 as_view() 方法:

from django.urls import path
from django.views.decorators.csrf import csrf_exempt

urlpatterns = [
    path('login/', csrf_exempt(LoginView.as_view()), name='login'),
]

模板中的 Token 插入

在 HTML 表单中,必须包含 {% csrf_token %} 标签以生成隐藏输入框:

<form method="post">
  {% csrf_token %}
  <input type="text" name="username" />
  <input type="password" name="password" />
  <button type="submit">登录</button>
</form>

渲染后会自动生成类似以下结构:

<input type="hidden" name="csrfmiddlewaretoken" value="ABC123xyz...">

AJAX 请求中的 CSRF 处理

使用 JavaScript 发送非表单请求(如 JSON 数据)时,需手动从 Cookie 提取 Token 并设置请求头:

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;
}

const csrftoken = getCookie('csrftoken');

$.ajax({
    url: '/api/v1/orders/',
    type: 'POST',
    data: JSON.stringify(orderData),
    contentType: 'application/json',
    headers: {
        'X-CSRFToken': csrftoken
    },
    success: function(result) {
        console.log('订单创建成功');
    }
});

Django 会检查 X-CSRFToken 请求头,并与 Cookie 中的值进行对比验证。

常见注意事项

  • 静态文件和公开 API 可考虑豁免 CSRF,但需确保不涉及会话状态更改。
  • 测试环境中禁用 CSRF 应谨慎操作,避免养成忽略安全的习惯。
  • 前后端分离项目建议使用其他认证机制(如 JWT),避免依赖 Session 和 CSRF。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。