📜  django csrf 表单 - Python (1)

📅  最后修改于: 2023-12-03 15:30:28.528000             🧑  作者: Mango

Django CSRF 表单

什么是 CSRF

Cross-site request forgery (CSRF),中文名为“跨站请求伪造”,简称为 CSRF。它是一种常见的 Web 漏洞,攻击者可以在不知情的情况下,伪造用户已登录的身份,对服务器进行非法操作,比如更改用户密码、发送邮件、转账等。

举个例子,一个名为 A 的用户登录了自己的网上银行,产生了一个登录状态。此时,该用户未退出账户,如果恶意网站 B 同时被访问,该网站 B 含有恶意代码,那么 A 用户在不知情的情况下,会误操作向 A 用户的银行账户发起转账请求并完成操作。

Django 中的 CSRF 保护

Django 在引入 CSRF(跨站请求伪造) 保护机制之前,对于用户登录信息的验证是基于 sessionid 和 cookies 的。而这种验证方法是存在安全漏洞的,比如中间人攻击、恶意程序等。

为了保证用户的请求是合法的,Django 引入了 CSRF 保护机制,在用户发出 POST、PUT、PATCH、DELETE 等非幂等请求时,Django 会对该请求进行验证,以保证请求来源是合法的。

Django 中的 CSRF 保护机制的基本思路为:向用户返回带有完整性验证信息的 CSRF Token,在和表单一起提交,后台需要对该 Token 进行验证,通过验证才可以接受该表单的提交数据。

Django 中的 CSRF Token

Django 的 CSRF Token,是一串随机生成的字符串,可以在表单中嵌入,且是唯一的。

Django 中的 CSRF Token 的生成方式为:

from django.middleware import csrf
token = csrf.get_token(request)  # 生成 csrf Token

生成的 Token 默认嵌入到表单中:

<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">

在表单中添加 CSRF Token 可以防止 CSRF 攻击,也保证了表单提交的安全性。

使用 Django 表单内置 CSRF Token

Django 自带了 CSRF Token 在表单内的实现,只需要在表单中添加 {% csrf_token %} 语句。

from django import forms

class MyForm(forms.Form):
    my_field = forms.CharField()

# 模板
<form method="POST">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">提交</button>
</form>
使用 Ajax 时的 CSRF Token

如果使用 Ajax 请求,需要在请求头中添加 CSRF Token。

$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", csrf_token);
        }
    }
});

其中 csrf_token 是 Django 在每个 request 中自动添加的 csrf_token。

防止 CSRF 攻击的其他措施
  • 使用 HttpOnly 的 cookies。
  • 在 header 中添加 X-Content-Type-Options: nosniff
  • 在 header 中添加 X-XSS-Protection: 1; mode=block
  • 在 header 中添加 Content-Security-Policy
  • 禁止使用 get 请求提交数据。
总结

通过使用 Django 中的 CSRF Token,可以有效地防止 CSRF 攻击,保证表单提交的安全性。同时,除了使用 Django 中的 CSRF Token,还需采取其他安全措施,以防范其他形式的攻击。