Django 给出“CSRF 令牌丢失或不正确”。即使在 POST 调用中传递它之后也会出错
Posted
技术标签:
【中文标题】Django 给出“CSRF 令牌丢失或不正确”。即使在 POST 调用中传递它之后也会出错【英文标题】:Django gives 'CSRF token missing or incorrect.' error even after passing it in the POST call 【发布时间】:2019-01-05 22:22:01 【问题描述】:我有一个 django 应用程序可以成功注册和登录用户。但是我无法注销用户。
在前端,我有一个包含电源按钮图标的网页,点击该图标会触发注销请求。
我在前端使用 Angular js
index.html
<div class="col-xs-2">
<span style="opacity: 0.5;font-family: FontAwesome;font-size: 14px;color:#838F98;text-align:center;cursor:pointer" ng-click="logout()">
<i class="fa fa-power-off" aria-hidden="true"></i>
</span>
</div>
这里我使用ngclick
来调用我的index.js
logout()
函数
index.js
$scope.logout = function()
var url = '/logout';
var toSend =
csrfmiddlewaretoken: ' csrf_token '
$http(
method: 'POST',
url: url,
data: toSend,
).then(function(response)
response.data;
)
;
这个函数调用我在 urls.py
中定义了一个auth views
的/logout
url
urls.py
from django.contrib.auth.views import login, logout
url(r'^logout$', logout, 'template_name': 'login.html'),
但是当我点击网页上的电源图标时,我得到一个403 Forbidden
错误。它说CSRF verification failed. Request aborted
。但是我在javascript POST
调用中传递了csrf 令牌。
我做错了什么?
【问题讨论】:
不是csrf_token
一个 <input type="hidden"...>
项目,所以现在你传递的不仅仅是令牌。
@WillemVanOnsem 哦,好的,那么正确的方法是什么?以下解决方案对我不起作用。
【参考方案1】:
确保将 csrf 令牌添加到配置模块中的 http 请求标头中,如下所示。
function config($httpProvider)
// state provider code
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
还要检查您的 django 设置是否有:
CSRF_COOKIE_HTTPONLY=True
CSRF_COOKIE_HTTPONLY 默认为 False,但当为 True 时,客户端 JavaScript 将无法访问 CSRF cookie。阅读更多关于这个here
【讨论】:
【参考方案2】:当我收到这些错误时,是因为 csrf 令牌不在 html 表单中,这是一个 Django 模板标签,将其添加到您的 html 模板中,然后通过 JavaScript 获取实际令牌以将其与 angular 一起使用 令牌将被隐藏,因此请使用浏览器检查 html 以确认它是否有效,您设置它的方式将不起作用,因为您传递的是模板标签的字符串,Django 应该执行该标签在您可以使用 JavaScript 从您的 html 标记中捕获它之前的 html,然后您可以将其发布到您的视图中
<div class="col-xs-2">
csrf_token
<span style="opacity: 0.5;font-family: FontAwesome;font-size: 14px;color:#838F98;text-align:center;cursor:pointer" ng-click="logout()">
<i class="fa fa-power-off" aria-hidden="true"></i>
</span>
</div>
【讨论】:
抱歉,这仍然不能解决问题【参考方案3】:您可以在 jquery 中创建一个函数来将 CSRF 令牌保存为 cookie,而不是在每次 AJAX 调用时传递 CSRF 令牌(这似乎是一个令人头疼的问题并添加到传递的数据数组中)。
请参阅docs。
创建一个文件“csrf_ajax.js”(或您选择的其他内容)将其粘贴到其中。
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;
var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method)
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
$.ajaxSetup(
beforeSend: function (xhr, settings)
if (!csrfSafeMethod(settings.type) && !this.crossDomain)
xhr.setRequestHeader("X-CSRFToken", csrftoken);
);
使用静态文件或相对引用加载脚本
现在您可以通过 POST 请求进行 AJAX 调用,而无需担心 CSRF 令牌。
希望这对您有所帮助。干杯
荣誉:)
【讨论】:
【参考方案4】:你可以试试这个:
第一步:添加 django-cors-headers
setting.py
-----------
CORS_ALLOW_HEADERS = (
'x-requested-with',
'content-type',
'accept',
'origin',
'authorization',
'X-CSRFToken'
)
在视图中添加装饰器
view.py
-------
from django.views.decorators.csrf import ensure_csrf_cookie
@ensure_csrf_cookie
def post(request):
## your logic
AngularJS 客户端(将令牌添加到请求标头)
$http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
你可以关注这个link
【讨论】:
以上是关于Django 给出“CSRF 令牌丢失或不正确”。即使在 POST 调用中传递它之后也会出错的主要内容,如果未能解决你的问题,请参考以下文章
Django:CSRF 令牌丢失或不正确。 / 避免 % csrf_token %
CSRF 令牌丢失或不正确。 Django + AngularJS