CSRF失败:CSRF令牌丢失或不正确

时间:2014-10-29 19:40:02

标签: django django-rest-framework

我正在使用Django 1.7和django-rest-framework。

我创建了一个API,它会返回一些JSON数据,并将其放入我的settings.py

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.AllowAny',),
    'DEFAULT_RENDERER_CLASSES': (
    #   'rest_framework.renderers.XMLRenderer',
    'rest_framework.renderers.JSONRenderer',
    #   'rest_framework.renderers.BrowsableAPIRenderer',
    )
}

当我进行GET调用时,它会返回所有数据,但是当我尝试使用PUT / PATCH时,我得到了:

--------Response Headers---------
Status Code: 403
Date: Wed, 29 Oct 2014 18:51:42 GMT
Vary: Cookie
Server: WSGIServer/0.1 Python/2.7.8
Allow: GET, POST, PUT, PATCH, HEAD, OPTIONS
X-Frame-Options: SAMEORIGIN
Content-Type: application/json
---------------------------------

--------Response Body-----------
{"detail": "CSRF Failed: CSRF token missing or incorrect."}
---------------------------------

只有当我登录时才会发生这种情况,如果我是匿名的,我可以正确地进行PUT / PATCH。

我尝试使用@csrf_exempt并且出错了,我已将rest_framework.permissions.AllowAny包含在设置中...

我不知道发生了什么。有谁知道这是什么问题?

14 个答案:

答案 0 :(得分:59)

当您使用SessionAuthentication时,您正在使用Django的身份验证,通常需要检查CSRF。 Django REST Framework仅针对SessionAuthentication强制执行此操作,因此您必须在X-CSRFToken标头中传递CSRF令牌。

Django documentation提供了有关使用jQuery检索CSRF令牌并在请求中发送它的更多信息。 CSRF令牌保存为名为csrftoken的cookie,您可以从HTTP响应中检索该cookie,该响应因使用的语言而异。

如果您无法检索CSRF Coo​​kie,则通常表明您不应使用SessionAuthentication。我建议根据您的需要调查TokenAuthenticationOAuth 2.0

答案 1 :(得分:4)

这就是我解决它的问题,我在表单中包含了csrf标记,并且在加载文档时使用jquery / javascrip获得了这样的csrf标记

var $crf_token = $('[name="csrfmiddlewaretoken"]').attr('value');

将其包含在jquery标题中,如下所示

 $.ajax({
            type: "POST",
            url: "/api/endpoint/",
            data: newEndpoint,
            headers:{"X-CSRFToken": $crf_token},
            success: function (newEnd) {
                console.log(newEnd);
                add_end(newEnd);
            },
            error: function () {
                alert("There was an error")
            }
        });

答案 2 :(得分:3)

我认为这是一个cookie问题。

永久解决方案:如果您使用的是邮递员,请首先通过单击“ X”清除现有的cookie。然后添加正确的cookie。

临时解决方案(用于调试):在您的settings.py中尝试:

'DEFAULT_AUTHENTICATION_CLASSES': [
    # 'rest_framework.authentication.SessionAuthentication',
    'rest_framework.authentication.BasicAuthentication',
]

答案 3 :(得分:2)

我遇到了类似问题,我已将csrf_exempt方法下的网址包裹为 -

from django.views.decorators.csrf import csrf_exempt

url(r'^api/v1/some-resource$', csrf_exempt(SomeApiView.as_view())),

答案 4 :(得分:2)

我们遇到了这个问题,事实证明这是邮递员的错。他们自动发送了csrftokensessionid默认值,我们没有在标头中传递它们。遵循本教程有助于解决该问题:https://avilpage.com/2019/02/django-tips-csrf-token-postman-curl.html

答案 5 :(得分:1)

1-搜索Cookie标头

enter image description here

2-将csrftoken与sessionid分开

3-添加X-CSRFToken = {..您在第2步中提取的csrftoken。}参见下文

enter image description here 4-重新发布

答案 6 :(得分:1)

// USING AJAX TO UPDATE DATABASE THROUGH REST API
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]);
            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);
        }
    }
});

答案 7 :(得分:1)

这发生在我使用邮递员测试 rest-auth 注册时 发生这种情况是因为邮递员发送了不正确的标头,一些旧的 cookie 和错误的内容类型,我认为这是某种错误,或者我错了

解决方案:所以我禁用了默认标题

手动输入内容类型和json正文(POST请求)

然后重新启用所需的标头

答案 8 :(得分:0)

从cookie中获取令牌:

function readCookie(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0;i < ca.length;i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1,c.length);
        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    }
    return null;
}

var csrftoken = readCookie('csrftoken');

在标头POST请求中发送令牌:

  this.$http.post(server,{params: {foo: 'bar'}}, {headers: {"X-CSRFToken":csrftoken }}).then(function (response) {
            this.response = response.data;
        },
        function (response) {
            console.log(response);
        });

答案 9 :(得分:0)

我有一个类似的问题,我用csrf_exempt包装了视图,但仍然遇到错误。原来,我把URL弄错了,所以它解决了一个“未找到”的回调(这不是CSRF的豁免),因此在我被告知URL错误之前抛出了一个异常。 >

答案 10 :(得分:0)

当您在Apache服务器上托管django网站时。 带有TokenAuthentication和SessionAuthentication的Djando rest框架将获得

  

CSRF失败:CSRF令牌丢失或不正确

要修复此打开的Apache配置文件-httpd.conf,请添加以下行:

WSGIPassAuthorization On

答案 11 :(得分:0)

我在here上找到了解决此错误的最简单方法。它非常适合我。

步骤:

继承SessionAuthentication类:

from rest_framework.authentication import SessionAuthentication, BasicAuthentication 

class CsrfExemptSessionAuthentication(SessionAuthentication):

    def enforce_csrf(self, request):
        return  # To not perform the csrf check previously happening

然后在您创建的APIView中执行以下操作:

class Object(APIView):
    authentication_classes = (CsrfExemptSessionAuthentication, BasicAuthentication)

    def post(self, request, format=None):

这将使您保持登录状态,并且将不再为此APIView检查CSRF令牌。

答案 12 :(得分:0)

在 settings.py 文件中

INSTALLED_APPS = [
...
...
...
...
'rest_framework.authtoken',
...
]

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    ),
}

在项目 urls.py 中

from rest_framework.authtoken import views

urlpatterns = [
    ....
    path('api-token-auth/',views.obtain_auth_token,name='api-token-auth')

]

打开终端

$ pip3 install httpie
$ python3 manage.py createsuperuser # if not created
$ http POST http://localhost:8000/api-token-auth/ username="username" password = "password"   # You will get token key (Just copy it) ex:a243re43fdeg7r4rfgedwe89320

<块引用> <块引用>

您的令牌密钥也将自动保存在您的数据库中

转到邮递员标题(如示例中所示) 例如:screenshot from postman ,where and how to paste accessed toke

然后插入您的令牌密钥。

<块引用>

You can take reference to get token key from this video

答案 13 :(得分:-5)

django1.8 python2.7

color = ['Red', 'Green', 'White']

我通过使用其他http方法来修复它; 哦,我再次面对它,这次是因为我粘贴了它,里面有一些看不见的字符