如何使用 Django 中间件来实现跨站点请求伪造(CSRF)保护?

2023-04-11 00:00:00 来实现 如何使用 伪造

Django 中内置了 CSRF 防御机制,可以通过中间件来实现。具体步骤如下:

  1. 在 settings.py 文件中配置 MIDDLEWARE:
MIDDLEWARE = [
    # ...
    'django.middleware.csrf.CsrfViewMiddleware',
    # ...
]
  1. 在前端页面中添加 CSRF Token:
{% csrf_token %}
  1. 如果使用 AJAX 请求,则需要在请求头中添加 CSRF Token:
var csrftoken = getCookie('csrftoken'); // 先获取 CSRF Token
$.ajax({
    url: '/your/api/url/',
    method: 'POST',
    data: { 'some': 'data' },
    headers: {
        'X-CSRFToken': csrftoken // 将 CSRF Token 添加到请求头中
    },
    success: function(data) {
        console.log(data);
    }
});
  1. 验证 CSRF Token:

Django 的中间件会自动验证 POST、PUT、DELETE 等请求中的 CSRF Token,如果验证失败会返回 403 错误。如果需要手动验证,可以通过下面的代码实现:

from django.middleware.csrf import CsrfViewMiddleware
from django.http import HttpResponseForbidden

class CsrfMiddleware(CsrfViewMiddleware):
    def process_view(self, request, callback, callback_args, callback_kwargs):
        # 排除某些视图不需要 CSRF Token 验证
        excluded_views = ['some_view', 'another_view']
        if not request.user.is_authenticated and callback.__name__ not in excluded_views:
            # 验证 CSRF Token
            if not self._csrf_token_is_valid(request):
                return HttpResponseForbidden()

这样,在视图函数中添加一个装饰器即可:

@csrf_exempt # 可以排除 CSRF Token 验证
def some_view(request):
    # ...

上面代码中的 csrf_exempt 是一个装饰器,用于排除某些视图不进行 CSRF Token 验证。

代码演示:

<form method="POST">
  {% csrf_token %}
  <label for="name">姓名:</label>
  <input type="text" name="name" id="name">
  <input type="submit" value="提交">
</form>

在 Django 的视图函数中可以直接获取 POST 中的数据:

from django.shortcuts import render

def submit_form(request):
    if request.method == 'POST':
        name = request.POST.get('name')
        return HttpResponse(f'Hello, {name}!')
    else:
        return render(request, 'form.html')

这样提交表单时就可以正确地获取到数据了。对于 AJAX 请求,需要在请求头中添加 CSRF Token,可以参考上面的代码演示。

相关文章