Forbidden (403)
CSRF verification failed. Request aborted.
Help
Reason given for failure:
CSRF token missing.
In general, this can occur when there is a genuine Cross Site Request Forgery, or when Django’s CSRF mechanism has not been used correctly. For POST forms, you need to ensure:
- Your browser is accepting cookies.
- The view function passes a
request
to the template’s render method. - In the template, there is a
{% csrf_token %}
template tag inside each POST form that targets an internal URL. - If you are not using
CsrfViewMiddleware
, then you must usecsrf_protect
on any views that use thecsrf_token
template tag, as well as those that accept the POST data. - The form has a valid CSRF token. After logging in in another browser tab or hitting the back button after a login, you may need to reload the page with the form, because the token is rotated after a login.
You’re seeing the help section of this page because you have DEBUG = True
in your Django settings file. Change that to False
, and only the initial error message will be displayed.
You can customize this page using the CSRF_FAILURE_VIEW setting.
解决方法
遇到 "CSRF verification failed" 错误通常是因为 Django 的 CSRF(Cross-Site Request Forgery) 保护机制在处理表单提交时没有找到有效的 CSRF token,导致请求被拒绝。
在 Django 中,CSRF 是一种常见的安全机制,用于防止恶意网站从用户的浏览器中发起恶意请求。在 POST 请求中,Django 需要验证请求是否包含有效的 CSRF token,以确认该请求是来自受信任的客户端。
常见原因和解决方法
1. 缺少 CSRF Token: 如果你在提交表单时没有在 HTML 中包含 CSRF token,Django 就会抛出 CSRF verification failed
错误。确保在每个 POST 请求的表单中都包含 {% csrf_token %}
。
解决方法: 在你的 HTML 表单中加入 {% csrf_token %}
:
<form method="post">
{% csrf_token %}
<!-- 你的表单字段 -->
<button type="submit">Submit</button>
</form>
2. 前端没有发送 CSRF Token: 如果你的表单是通过 JavaScript 发送的,可能需要手动将 CSRF token 添加到请求头中。你可以从 csrftoken
cookie 中提取 CSRF token,并将它添加到请求头中。
解决方法: 如果你通过 AJAX 提交数据,确保在请求头中发送 CSRF token:
// 获取 CSRF token
const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value;fetch('/your-url/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken // 添加 CSRF token
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
3.如果你使用的是 jQuery,可以通过以下方式全局设置 CSRF token
$.ajaxSetup({
headers: {
'X-CSRFToken': getCookie('csrftoken') // 从 cookie 获取 CSRF token
}
});
并且你可以通过以下方式获取 CSRF 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;
}
4..未启用 CSRF Middleware: 如果 Django 的 CSRF middleware 没有启用,也会导致 CSRF 错误。检查你的 settings.py
文件,确保 MIDDLEWARE
中包含了 'django.middleware.csrf.CsrfViewMiddleware'
。
解决方法: 在 settings.py
中确认 MIDDLEWARE
配置项包括 CsrfViewMiddleware
:
MIDDLEWARE = [
# 其他中间件
'django.middleware.csrf.CsrfViewMiddleware',
]
5.浏览器禁用了 Cookies: CSRF 保护机制依赖于浏览器支持和启用 cookies,尤其是 CSRF token 会存储在一个名为 csrftoken
的 cookie 中。如果用户禁用了 cookies,可能会导致 CSRF 校验失败。
解决方法: 确保用户启用了 cookies 或者检查浏览器设置,确保 csrftoken
cookie 被正确地存储和发送。
6, 跨站请求: 如果你正在使用不同域名(跨站请求)发起请求,Django 可能会拒绝该请求。CSRF 保护机制要求请求来源域名与目标域名匹配。
解决方法:
- 确保跨域请求遵循 CORS(跨域资源共享)策略。如果是跨域请求,需要确保在响应头中包括
Access-Control-Allow-Credentials
,并确保允许传递 cookie。
在 settings.py
中启用 CORS:
CORS_ALLOWED_ORIGINS = [
'https://yourfrontenddomain.com',
]
7,
使用 @csrf_exempt
装饰器禁用 CSRF 校验: 如果你确定某些视图不需要 CSRF 校验,可以使用 @csrf_exempt
装饰器来禁用 CSRF 校验。
解决方法:
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def your_view(request):
# 视图逻辑
return HttpResponse('No CSRF required')
但是,强烈建议只在必要时使用此装饰器,以免造成安全风险。
总结:
- 确保表单中包含
{% csrf_token %}
。 - 在通过 JavaScript 发起 POST 请求时,确保将 CSRF token 包含在请求头中。
- 检查浏览器是否启用了 cookies。
- 如果你使用的是跨域请求,确保处理好 CORS 和 CSRF 头部。
- 如果你希望禁用 CSRF 校验,可以使用
@csrf_exempt
,但这要谨慎使用。
这些步骤应当能够帮助你解决 CSRF 校验失败的问题。如果问题仍然存在,检查服务器和浏览器的配置,确保它们能够正确地处理 CSRF 相关的请求。