CSRF Failed: CSRF token missing or incorrect

2019-01-17 15:00发布

问题:

I'm using Django 1.7 and django-rest-framework.

I made an API that returns me some JSON data putting this in my 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',
    )
}

When I make GET calls, it returns me all the data, but when I try with PUT/PATCH I get:

--------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."}
---------------------------------

This only happens when I am logged in, if I am anonymous I can PUT/PATCH correctly.

I have tried with @csrf_exempt and I got errors, I have included the rest_framework.permissions.AllowAny in the setting...

I have no idea what's going on. Does anyone know what the issue is?

回答1:

When you are using SessionAuthentication, you are using Django's authentication which usually requires CSRF to be checked. Django REST Framework enforces this, only for SessionAuthentication, so you must pass the CSRF token in the X-CSRFToken header.

The Django documentation provides more information on retrieving the CSRF token using jQuery and sending it in requests. The CSRF token is saved as a cookie called csrftoken that you can retrieve from a HTTP response, which varies depending on the language that is being used.

If you cannot retrieve the CSRF cookie, this is usually a sign that you should not be using SessionAuthentication. I recommend looking into TokenAuthentication or OAuth 2.0 depending on your needs.



回答2:

This is what i did to solve it, i included csrf token to the form and using jquery/ javascrip got the csrf token like this when document loaded

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

the included it on jquery headers as follow

 $.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")
            }
        });


回答3:

I had similar problem, I've wrapped my URLs under csrf_exempt method as -

from django.views.decorators.csrf import csrf_exempt

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


回答4:

Get token from 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');

Send token in headers POST request:

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


回答5:

I had a similar problem where I'd wrapped the views with csrf_exempt and was still encountering errors. It turned out that I was getting the URL wrong, so it was resolved to a "not found" callback (which wasn't exempt from CSRF) and was hence throwing an exception before I could be told that the URL was wrong.



回答6:

1- Search for the Cookie header

2- Separate the csrftoken from the sessionid

3- Add the X-CSRFToken={..the csrftoken that you extracted in step 2..} see below

4- Post again



回答7:

When you host django website on Apache server. Djando rest framework with TokenAuthentication and SessionAuthentication will get

CSRF Failed: CSRF token missing or incorrect

To fix this open Apache configuration file - httpd.conf Add following line:

WSGIPassAuthorization On