如何使用 Django 中间件来实现跨站点请求伪造(CSRF)保护?
Django 中内置了 CSRF 防御机制,可以通过中间件来实现。具体步骤如下:
- 在 settings.py 文件中配置 MIDDLEWARE:
MIDDLEWARE = [ # ... 'django.middleware.csrf.CsrfViewMiddleware', # ... ]
- 在前端页面中添加 CSRF Token:
{% csrf_token %}
- 如果使用 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); } });
- 验证 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,可以参考上面的代码演示。
相关文章