Django 中间件使用 ajax 使用 HTTPS POST 引发 403 错误

Posted

技术标签:

【中文标题】Django 中间件使用 ajax 使用 HTTPS POST 引发 403 错误【英文标题】:Django middleware throws 403 error with HTTPS POST using ajax 【发布时间】:2012-08-10 07:14:22 【问题描述】:

我对这里的许多部分(Django/Ajax 等)都很陌生,所以虽然我了解高级 CSFR 图片,但我对细节没有完整的掌握。

由于传递的数据量较大,我需要将请求从 GET 转换为 PUT。高级别的,我正在通过 HTTPS 对 django 应用程序进行 AJAX POST API 调用。调用是从提供页面的同一域进行的。

但是,我不断收到“未设置 CSRF cookie”错误。

我正在使用 Django 1.4

为了通过 CSRF 保护,我在标题中包含了其他帖子中提到的 X-CSFRToken,并在发布的数据中包含了 csrf_token 标签。但是,看起来该标签并没有被令牌替换。 X-CSFRToken 值在请求中作为 NULL 发送。不知道为什么它没有设置。

我的印象是我不需要在页面视图中使用 ensure_csrf_cookie(),因为我在 ajaxSetup 中的 POST 之前获取了 cookie,但我也尝试过。

知道我做错了什么?

相关代码:

siteUrl = "https://localhost:8443/"

$.ajaxSetup( 
     beforeSend: function(xhr, settings) 
         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;
         
         if (new RegExp("^"+siteUrl.replace("\\","\\\\")+".*").test(settings.url)) 
             // Only send the token to URLs from our site.
             xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
         
      
);


$.ajax(
    url: submitUrl,
    data: 'network_ids': JSON.stringify(network_ids),
            'csrfmiddlewaretoken': ' csrf_token ',
    type: 'POST',
    crossDomain: true,
    dataType: 'json',
    cotentType: 'application/json',
    success: function(mydata) 
        console.log(mydata);
    ,
    error: function(jqXHR, textStatus, errorThrown) alert(textStatus); alert(errorThrown)
)

【问题讨论】:

【参考方案1】:

您有多种选择: 此代码清单显示您从 cookie 中获取 CSRF 令牌:https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax

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]);
            // 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;

getCookie('csrftoken');

并假设 javascript 函数正在提交到 django 视图,您可以告诉该视图忽略 csrf 保护。 https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#django.views.decorators.csrf.csrf_exempt

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def my_view(request):
    return HttpResponse('Hello world')

【讨论】:

【参考方案2】:

你的 js 是通过 Django 的模板引擎提供的吗?否则 csrf_token 将不会被评估。你检查过它实际上是 POST 到服务器的吗?

同样根据docsajaxSend 事件背后的想法是您不必必须显式传递csrf_token

我注意到您的 ajaxSetup 与文档中的略有不同。这可能是正确的,但是我会从文档中复制原件。

【讨论】:

以上是关于Django 中间件使用 ajax 使用 HTTPS POST 引发 403 错误的主要内容,如果未能解决你的问题,请参考以下文章

Django 之AJAX

30_Django中关于使用ajax发送请求中`csrf_token`的问题和解决

Python-Django-Ajax进阶3

Django

ajax和form表单,django的中间件

RBAC在Django中基于中间件的AJAX应用案例