在向管理员进行身份验证时,CSRF失败403,但在未经过身份验证时同样正常

时间:2018-03-28 22:00:48

标签: angularjs django rest filter django-queryset

我想是另一个问题的新手类型。

AngularJS使用PATCH方法引发:

"CSRF Failed: CSRF token missing or incorrect."

饼干:

Cookie:arp_scroll_position=0; sessionid=ix36xi2u9bijih2x1npswjlranfm7wjy; csrftoken=w54t2iWlU6oYBoYpeoZtkeWHluAgFmZOIbNeVsfo9pGgCD8OnPzoCdxJNmbfl2aM

但只有当我在另一个标签中对“管理员”面板进行身份验证时。 如果我没有登录,同样的请求也可以正常工作。

Cookie:arp_scroll_position=0; csrftoken=w54t2iWlU6oYBoYpeoZtkeWHluAgFmZOIbNeVsfo9pGgCD8OnPzoCdxJNmbfl2aM

这是非常简单的JSON推送:

.factory('MyName', function($resource) {
  return $resource('/api/resource/:pk/', {'pk': '@pk'}, {
      'update': {
        method: 'PATCH' // this method issues a PUT request
      },
    });
});

使用{"pk":3,"gt":"angularjs-auth"}

等JSON内容

与此同时,另一个" html"使用单独的AngularJS应用程序定义在经过身份验证和未经过身份验证时都适用于这两种情况,但这次我使用dropzone可能会为我透明地解决问题。

.factory('UploadFile', function($resource) {
  return $resource('/api/files/:pk', {'pk': '@pk'}, {
        'save': {
            method: 'POST',
              transformRequest: transformImageRequest,
            headers: {'Content-Type':undefined}
        },
    });
});

不是Authenticade POST(不是PATCH,但可能这没有什么区别):

Cookie:arp_scroll_position=0; csrftoken=w54t2iWlU6oYBoYpeoZtkeWHluAgFmZOIbNeVsfo9pGgCD8OnPzoCdxJNmbfl2aM

我在这里看到的内容是多部分/表格数据本身也包含CSRF(这是解决问题的诀窍吗?)

------WebKitFormBoundaryXUBwTTaSIiKwTvyx
Content-Disposition: form-data; name="csrfmiddlewaretoken"

经过验证:

Cookie:sessionid=kaw00iaxwpq3puxcc94dy9v8yxf7rfyh; csrftoken=49KSaqsZykxuYRvJsEhpKlCyqP1ZnVQAubO4bPKs0u2qEcm0hpVvutMoIdUW9gV6; arp_scroll_position=0


------WebKitFormBoundaryelub0ZsHFENNbUmp
Content-Disposition: form-data; name="csrfmiddlewaretoken"

dqeieK1GdnYD9QTVRbt4ibQ6q0u8o8mkDsiuf9j9FxtzPbKcGW7a2j0WIon5atrQ

寻求帮助和建议改变什么,因为我确实错过了一些小部分来解决它。

{%csrf_token%}是html的一部分,并尝试将其包含在部分中。

与此同时,Postman使用" No auth"和#34; Basic Auth"。当然,它不像AngularJS PATCH那样镜像,但似乎我做了一些愚蠢的错误,因为只有我的AngularJS PATCH不起作用。

编辑1

以下默认元素(包括身份验证)是settings.py

的一部分
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

2 个答案:

答案 0 :(得分:0)

通过对Django REST Framework视图的请求,您通常不需要CSRF令牌......

除非您使用基于会话/ cookie的身份验证进行身份验证(无论是否在管理员身份,都无关紧要)。

除了使用您的CSRF令牌发送multipart/form-data之外,您可以通过两种方式绕过它。

第一种方法是使用X-CSRFToken header在请求中传递令牌(您的JS逻辑必须在发出请求时设置该标头)

第二种方法是使用另一种身份验证方法。如果设置文件中的list of authentication backends更高,则可以与基于cookie /会话的一起使用。 REST框架将从列表中选择第一个有效并丢弃其他的框架,因此基于会话/ cookie的将无法启用CSRF验证。

答案 1 :(得分:0)

感谢GwynBleidD提供的帮助和提示。 不知道它是如何工作的,我可以拉我的头发几个小时试图解决问题,一旦问题发布/问我找到解决方案。

在这种情况下,我需要做的就是遵循我的AngularJS代码:

myApp.config(['$httpProvider', function($httpProvider) {
    $httpProvider.defaults.xsrfCookieName = 'csrftoken';
    $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}]);

这个固定的问题完全可以完美地运作。

@GwynBleidD,我很高兴听到推荐使用哪种身份验证方法。