Django CSRF 防护机制详解与实战配置

一只小鹿
一只小鹿
发布时间:2026-10-13 | 4人浏览过
原创

本文深入解析 Django 框架中 CSRF 防护机制的工作原理,涵盖 CsrfViewMiddleware 的配置、{% csrf_token %} 模板标签在表单中的应用,以及 Ajax 请求中 X-CSRFTOKEN 头部的设置方法。同时提供全局与局部禁用 CSRF 验证的替代方案及风险提示,帮助开发者安全处理 POST 请求。

关于 CSRF 的基本概念

CSRF(Cross-site request forgery,跨站请求伪造),也常缩写为 XSRF,是一种针对网站的恶意攻击手段。其核心在于利用受信任用户发起的请求来执行非授权操作。

通俗来说,攻击者窃取了用户的身份凭证,并以用户的名义发送恶意请求。例如,用户登录网站 A 后,浏览器保存了相关的 Cookie 以维持会话状态。当用户随后访问恶意网站 B 时,B 网站可能包含诱导代码,试图向网站 A 发起请求。此时,浏览器会自动携带网站 A 的 Cookie 发送请求,服务器端无法区分这是用户真实操作还是被伪造的请求,从而可能导致数据泄露或篡改。

Django 提供的 CSRF 防护机制

Django 在首次响应来自特定客户端的请求时,会在服务器端生成一个随机 token 并将其放入 Cookie 中。此后,所有 POST 请求都必须携带此 token,以此实现防护。

通过上述机制,可以有效防止 CSRF 攻击。

具体实现步骤如下: 1. Django 会在返回的 HTTP 响应 Cookie 中添加一个名为 csrftoken 的字段,其值为自动生成的 token。 2. 所有 POST 表单提交时,必须包含一个名为 csrfmiddlewaretoken 的字段。在模板中只需添加相应的标签,Django 会自动生成该字段。 3. 在处理 POST 请求前,Django 会验证请求 Cookie 中的 csrftoken 与表单提交的 csrfmiddlewaretoken 是否一致。若一致,则视为合法请求;否则,判定为潜在的 CSRF 攻击,并返回 403 Forbidden 错误。 4. 对于所有 Ajax POST 请求,需添加一个名为 X-CSRFTOKEN 的 Header,其值应等于 Cookie 中的 csrftoken 值。

Django 中如何使用 CSRF 防护

  • 首要原则是:GET 请求不应产生副作用。即处理 GET 请求的代码对资源的访问必须严格保持“只读”性质。
  • 确保已启用 django.middleware.csrf.CsrfViewMiddleware 中间件。
  • 其次,在所有 POST 表单元素中,必须添加 {% csrf_token %} 标签。
  • 在渲染模板时,使用 RequestContext。RequestContext 会处理 csrf_token 标签,自动为表单生成一个名为 csrfmiddlewaretoken 的 input 字段。

Django 对 CSRF 的防范实践

Django 内置了防止 CSRF 攻击的功能,但初学者可能不清楚具体用法,从而遇到意外问题。

例如,正常的表单提交操作可能会因缺少配置而报错。

在 Django 中,GET 请求无需 CSRF 认证,而 POST 请求必须通过正确的认证才能返回预期结果。

首先处理表单提交的 CSRF 验证问题:通常在 POST 表单中加入 {% csrf_token %} 即可。

<form method="POST" action="#">
{% csrf_token %}
  <input name='password' value='用户密码'>
</form>

添加该标签后,再次提交 POST 表单通常不会再出现错误。

另一种思路是禁用 CSRF 验证。

但需注意,这样做可能带来安全风险,务必权衡利弊。

全局禁用方法:在 settings 文件中找到 CSRF 中间件配置,直接注释掉即可。

局部禁用方法:在表单提交的对应视图函数上添加 @csrf_exempt 装饰器。

——————————————————————

{% csrf_token %} 实际上是一种模板语法,它将项目的 token 值写入前端页面的表单中。该值在项目创建时自动生成,可在 settings 文件中查看相关配置。

——————————————————————–

接下来介绍 Ajax 调用时的处理方式。

在使用 jQuery 的 ajax 或 post 方法前,可以插入一段 JavaScript 代码来处理 CSRF Token。

jQuery(document).ajaxSend(function(event, xhr, settings) {
  function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie != '') {
      var cookies = document.cookie.split(';');
      for (var i = 0; i < cookies.length; i++) {
        var cookie = jQuery.trim(cookies[i]);
        // Does this cookie string begin with the name we want?
        if (cookie.substring(0, name.length + 1) == (name + '=')) {
          cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
          break;
        }
      }
    }
    return cookieValue;
  }
  function sameOrigin(url) {
    // url could be relative or scheme relative or absolute
    var host = document.location.host; // host + port
    var protocol = document.location.protocol;
    var sr_origin = '//' + host;
    var origin = protocol + sr_origin;
    // Allow absolute or scheme relative URLs to same origin
    return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
      (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
      // or any other URL that isn't scheme relative or absolute i.e relative.
      !(/^(\/\/|http:|https:).*/.test(url));
  }
  function safeMethod(method) {
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
  }

  if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
    xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
  }
});

或者,可以直接在模板文件中写入相关配置。

$.ajaxSetup({
  data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
});

以上为本文全部内容,希望对您的学习有所帮助,欢迎继续支持本站。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表