【问题标题】:Forbidden (CSRF token missing or incorrect.) | Django and AJAX禁止(CSRF 令牌丢失或不正确。) | Django 和 AJAX
【发布时间】:2020-10-12 23:06:34
【问题描述】:

:(

我正在发出 ajax 请求,但出现此错误:

Forbidden (CSRF token missing or incorrect.): /manager/ajax/
[23/Jun/2020 00:00:46] "POST /manager/ajax/ HTTP/1.1" 403 2517
[23/Jun/2020 00:01:18] "GET /manager/test/update/3/ HTTP/1.1" 200 10249
Forbidden (CSRF token missing or incorrect.): /manager/ajax/
[23/Jun/2020 00:01:18] "POST /manager/ajax/ HTTP/1.1" 403 2517
[23/Jun/2020 00:01:22] "GET /manager/test/update/3/ HTTP/1.1" 200 10249
Forbidden (CSRF token missing or incorrect.): /manager/ajax/
[23/Jun/2020 00:01:23] "POST /manager/ajax/ HTTP/1.1" 403 2517

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 = cookies[i].trim();
            // 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');

fetch('/manager/ajax/', {
    method: 'POST',
    body: JSON.stringify({
        csrfmiddlewaretoken: csrftoken,
        title: 'hello!!!! :(',
    }),

    headers: {
        "Content-Type": "application/x-www-form-urlencoded"
    }
})
.then(response => response.json())
.then(json => console.log(json))

我的看法:

def delete_exam_question(request):
    print(request.method)

    if request.is_ajax:
        print(request.POST)
        #exam_question = ExamQuestion.objects.get(title = request.POST.get('title'))
        #exam_question.delete()

    return JsonResponse({'deleted': True})

我尝试像在this question ("application/x-www-form-urlencoded") 中那样修复它,我已经尝试指示"application/json",但它不起作用... :(

我通过了令牌 (csrftoken),但它仍然不起作用,我已经尝试了所有方法,但我无法让它起作用。


更新:

("Content-Type" => "application/x-www-form-urlencoded")

使用装饰器csrf_exempt 装饰视图。 POST数据是:

<QueryDict: {'{"csrfmiddlewaretoken":"4gTL9H17LIgTFc3HseYFuT6JQMbkEHxiuGXVxu9WWKTgN0gVmUtJJPDgwem0zj4U","title":"holaaa"}': ['']}>

这就是他给我错误的原因,但这种情况非常罕见。而且我不知道如何纠正它,有什么想法吗?我不太懂 JavaScript。

我把Conten-Type改成了"application/json",POST数据是:

<QueryDict: {}>

但是,我打印了request.body,并打印了:

b'{"csrfmiddlewaretoken":"4gTL9H17LIgTFc3HseYFuT6JQMbkEHxiuGXVxu9WWKTgN0gVmUtJJPDgwem0zj4U","title":"holaaa"}'

发生了什么事? :(

【问题讨论】:

  • 您是否尝试过记录 csrftoken 的值以查看它是什么? IE。 console.log(csrftoken)
  • 感谢您的回复,是的,打印令牌... :(

标签: javascript python django ajax


【解决方案1】:

看看下面的源代码,如果使用XMLHttpRequest 调用,你需要明确告诉 Django 这个请求。最好避免使用is_ajax 来检测ajax,因为它将在未来的版本中被弃用

def is_ajax(self):
    warnings.warn(
        'request.is_ajax() is deprecated. See Django 3.1 release notes '
        'for more details about this deprecation.',
         RemovedInDjango40Warning,
         stacklevel=2,
      )
     return self.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'

在标题中添加这些行,对于 ajax 请求,首选使用 X-CSRFToken,因为它还支持其他请求方法,如 DELETE、PUT 等

# django internllay change '-' to '_' and add prefix HTTP in front of the value
# so 'X-Requested-With' becomes HTTP_X_REQUESTED_WITH, which is used by is_ajax function 
{
   'X-Requested-With': 'XMLHttpRequest',
   'X-CSRFToken': <your_csrftoken_value>
}

编辑

$('#sub-btn').click(function(e){ 
    e.preventDefault();
    $.ajax( 
        { 
        type:"POST", 
        beforeSend: function (xhr) {
            xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
            xhr.setRequestHeader('X-CSRFToken', <your_csrftoken_value>);
        },
        url: <your_url>, 
        data: {test: 'test'},
        success: function(data){ 
           console.log(data)
        }
    });
})  

另外,如果你使用jQuery并使用这种格式发送数据,你可以在request.POST接收数据

【讨论】:

  • 它有效!!,我不再需要使用 csrf_exempt 装饰器。但是相反,我没有收到数据,request.POST 是空的,我只能通过request.body 访问数据。谢谢。
  • 每个人都通过request.POST 接收数据,为什么不是我?,只是它对我不起作用...... :(
  • @Julio Cesar,通常情况下,我们通过$.ajax发送数据,通过这样做,数据在request.POST中可用,但如果您需要fetch api,您可以使用data = json.loads(request.body)加载数据,干杯
  • 那么通过request.body获取数据不是不好的做法吗?
猜你喜欢
  • 2019-11-24
  • 2021-01-08
  • 2015-10-15
  • 2020-12-24
  • 2017-01-13
  • 2021-10-24
  • 1970-01-01
  • 1970-01-01
  • 2017-09-14
相关资源
最近更新 更多