Django给出“ CSRF令牌丢失或不正确”。即使在POST调用中传递了错误之后

时间:2018-07-29 13:40:27

标签: javascript python angularjs django django-csrf

我有一个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

中为其定义了/logout的{​​{1}} url

urls.py

auth views

但是,当我单击网页上的电源图标时,出现from django.contrib.auth.views import login, logout url(r'^logout$', logout, {'template_name': 'login.html'}), 错误。它显示为403 Forbidden。但是我在JavaScript CSRF verification failed. Request aborted调用中传递了csrf令牌。 / p>

我在做什么错了?

4 个答案:

答案 0 :(得分: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

的更多信息

答案 1 :(得分:0)

当我得到这些错误是因为csrf令牌不在html表单中时,这是Django模板标签,将其添加到您的html模板中,然后通过JavaScript获取实际的令牌以将它与angular一起使用 令牌将被隐藏,因此请使用浏览器检查html以确认它是否有效,因为您传递了模板标签的字符串,所以设置方法无法正常工作,Django应该在其中执行该标签html,然后才能使用html标签中的JavaScript捕获它,然后将其发布到视图

<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>

答案 2 :(得分:0)

您可以在jquery中创建一个函数来将CSRF令牌另存为cookie。

您不必在每次AJAX调用时都传递CSRF令牌(这似乎很麻烦,并且会添加到传递的数据数组中),而不是在CSQuery中创建一个函数。

请参阅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令牌。

希望这对您有所帮助。干杯

荣誉:)

答案 3 :(得分:0)

您可以尝试以下方法:

第一步:添加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