Django CSRF 跨站 AJAX 问题

Posted

技术标签:

【中文标题】Django CSRF 跨站 AJAX 问题【英文标题】:Django CSRF cross site AJAX issue 【发布时间】:2017-07-01 07:36:33 【问题描述】:

我在 localhost:8000 有一个后端服务器,在 localhost:3000 有一个前端服务器。后端是 Django,我安装了 corsheaders 包,我发出 GET 请求没有问题。当我打开我的网站时,第一个 GET 请求成功设置了 CSRF 令牌(我可以在开发工具中看到 cookie)。

我在 settings.py 中有这个:

CORS_ORIGIN_WHITELIST = (
    'localhost:3000'
)

CORS_ALLOW_METHODS = (
    'DELETE',
    'GET',
    'OPTIONS',
    'PATCH',
    'POST',
    'PUT'
)

CORS_ALLOW_HEADERS = (
    'accept',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
)

CSRF_TRUSTED_ORIGINS = (
    'localhost:3000',
)

CORS_ALLOW_CREDENTIALS = True

现在我正在尝试发出 POST 请求,但我一直被服务器拒绝:

403 - Forbidden (CSRF cookie not set.): /myapp/myview/

这就是我的 JS 的样子:

let csrftoken = utils.getCookie('csrftoken'); // logged this on the console, the token is really here

jQuery.ajaxSetup(
  beforeSend: function(xhr, settings) 
    xhr.setRequestHeader("X-CSRFToken", csrftoken);
  
); // this might be wrong - I did read it is used only if it's not cross site, but I still gave it a try

jQuery.ajax(
  url: url,
  type: 'POST',
  data: attr: value, csrfmiddlewaretoken: csrftoken
)...

我只尝试过在 AJAX 数据中使用 csrfmiddlewaretoken。我只尝试设置请求标头。我都试过了。仍然没有运气。我显然错过了一些东西;我以前从未尝试过在 Django 中跨站点进行 POST。

有什么建议吗?

编辑:我发现问题出在其他地方。

【问题讨论】:

查看github.com/ottoyiu/django-cors-headers @PiyushS.Wanare 我已经在使用 django-cors-headers,但现在我已经使用 CORS_ALLOW_HEADERS/METHODS、CSRF_TRUSTED_ORIGINS 和 CORS_ALLOW_CREDENTIALS 扩展了我的设置,但它仍然不起作用,我明白了同样的错误信息。 您发现问题出在其他地方?您能否向我们指出该信息或关闭问题? 【参考方案1】:

尝试将 XSRF-Token 放在 Ajax 请求的标头中。

 $.ajax(
         url : urlToCall, // the endpoint
         type : "POST", // http method
         headers:  "X-CSRFToken": "your token here" ,
         success : function(response) 
            console.log('success', response); 
                ,
            error : function(xhr,errmsg,err) 
                console.log(xhr.status + ": " +  xhr.responseText); //  provide a bit more info about the error to the console
            
    );

【讨论】:

【参考方案2】:

我能够做到:

$.ajax(
     url : urlToCall, // the endpoint
     type : "POST", // http method
     data : 
         csrfmiddlewaretoken: "Your token",
         data...
     ,

     success : function(response) 
        console.log('success', response); 
            ,
        error : function(xhr,errmsg,err) 
            console.log(xhr.status + ": " +  xhr.responseText); //  provide a bit more info about the error to the console
        
);

希望对你有帮助!

【讨论】:

不,这与我发布的问题中的示例基本相同。

以上是关于Django CSRF 跨站 AJAX 问题的主要内容,如果未能解决你的问题,请参考以下文章

ajax向Django前后端提交请求和CSRF跨站请求伪造

自动化运维Python系列之Django CSRF跨站请求伪造中间件

Django的CSRF

21)django-csrf(跨站请求伪造)

1205 CSRF跨站请求与django中的auth模块使用

Django-csrf跨站请求伪造