【问题标题】:Django authentication : CSRF FailedDjango 身份验证:CSRF 失败
【发布时间】:2016-05-09 16:47:55
【问题描述】:

有时我无法登录我的应用程序。

身份验证由 Django API 处理。

但有时它会在结果对象中使用此值返回 403 错误:

responseText: "{"detail":"CSRF Failed: CSRF token missing or incorrect."}"

但在我的应用程序中,我有:

angular.module('app')
  .config(function(ezLayoutProvider, $httpProvider) {
    ezLayoutProvider.register(layoutName, {templateUrl: './main.html'});
    ezLayoutProvider.setDefault(layoutName);
    var getCookie = function(cookieName) {
      var cookieValue = null;

  if (document.cookie && document.cookie !== '') {
    var cookies = document.cookie.split(';');
    for (var i = 0; i < cookies.length; i++) {
      var cookie = cookies[i].trim();
      if (cookie.substring(0, cookieName.length + 1) === (cookieName + '=')) {
        cookieValue = decodeURIComponent(cookie.substring(cookieName.length + 1));
        break;
      }
    }
  }
  return cookieValue;
};

$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
$httpProvider.defaults.headers.common['X-CSRFToken'] = getCookie('csrftoken');
console.log($httpProvider.defaults.headers.common);
})

在我尝试登录之前,控制台显示令牌已正确设置。

奇怪的是,一旦我从浏览器中清除了我的 cookie 和缓存,它就可以工作了。

所以我猜这与 Django 的会话有关?

这是我的 settings.py 的一部分:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.DjangoModelPermissions',
    ),
}

REST_PROXY = {
    'HOST': 'http://localhost:5000'
}

CORS_ORIGIN_ALLOW_ALL = True

AUTHENTICATION_BACKENDS = (
    'auth.ldap.LDAPBackendFR',
    'auth.ldap.LDAPBackendUS',
    'auth.ldap.LDAPBackendHK',
    'auth.ldap.LDAPBackendIN',
    'django.contrib.auth.backends.ModelBackend',
)

另一个奇怪的点是它似乎也适用于:

Object {Accept: "application/json, text/plain, */*", X-Requested-With: "XMLHttpRequest", X-CSRFToken: null}

作为$httpProvider.defaults.headers.common

【问题讨论】:

    标签: javascript python angularjs django django-rest-framework


    【解决方案1】:

    你为什么使用$httpProvider.defaults.headers.common['X-CSRFToken'] = getCookie('csrftoken');?我不是 AngularJS 专家,但应该不需要这条线。

    Django documentation 是这么说的:

    如果您使用的是 AngularJS 1.1.3 和更新版本,则使用 cookie 和标头名称配置 $http 提供程序就足够了:

    $http.defaults.xsrfCookieName = 'csrftoken';
    $http.defaults.xsrfHeaderName = 'X-CSRFToken';
    

    据我了解,您的代码应该是这样的:

    $httpProvider.defaults.xsrfCookieName = 'csrftoken';
    $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
    $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
    /* Not needed, causes harm! */
    /* $httpProvider.defaults.headers.common['X-CSRFToken'] = getCookie('csrftoken'); */
    console.log($httpProvider.defaults.headers.common);
    

    这也应该解释为什么 X-CSRFToken: null 有效。

    【讨论】:

    • 我只是注意到每当我登录到管理界面时就会发生这种情况,所以我的猜测是一个令牌会擦除另一个令牌。这样,它就可以工作了,但是,如果我还登录了管理员,我就无法退出应用程序。
    【解决方案2】:

    如果我没记错的话,Django 的 CSRF 有一个他们工作的时间框架。

    我有时会遇到这个问题并刷新表单,因此 CSRF 确实对我有用。

    【讨论】:

    • 它不适合我,用户通常需要清除它的cookie才能在它发生时登录。我认为这可能与 Django 中的会话处理有关。
    • 清除 cookie 也会清除 csrf 令牌,这就是您使用 getCookie('csrftoken') 的原因
    猜你喜欢
    • 2022-01-11
    • 2012-09-08
    • 2015-06-02
    • 1970-01-01
    • 2017-03-29
    • 2011-06-14
    相关资源
    最近更新 更多