如何处理两个网站的一个后端CSRF问题在一个浏览器?

2024-10-04 05:23:30 发布

您现在位置:Python中文网/ 问答频道 /正文

如何在一个浏览器中处理独立家庭网站和管理网站CSRF问题?在

我们为它编写了一个家庭网站前端和一个管理网站前端(有两个前端),在前端使用JavaScript。
因为这两个站点都很大,所以我们在Nginx中把它们作为vhost。它们是两个地点。我使用Python(Django)编写一个后端,两个站点都调用一个后端。在

主页使用Nginx的default.conf,管理网站使用vhosts/admin.conf。在

这是测试域:

http://www.ajw123.xyz作为主页。
http://admin.ajw123.xyz作为管理网站。在

我的问题是当我在浏览器中使用主页上的帐户登录时:

enter image description here

然后我用这个账号登录到管理员网站(或其他账号),抛出CSRF Token错误:

enter image description here

您可以看到csrftoken两者都是:

csrftoken=L5bRGEXDvW9dJaXsanLlMTOrxxGpxJCw6vji1zQtjzYrskOq0FBjQtfkhvFKFDmj; 

在预览中:

enter image description here

CSRF Failed: CSRF token missing or incorrect.

我将Django Rest框架用于restapi,我们的前端同事编写了两个站点(一个是普通用户的前端和后端站点,另一个是管理员的后端站点),并且都在使用我的restapi。在


Tags: djangohttpadmin站点网站conf管理员家庭
3条回答

CSRF令牌本质上是一个可检索的cookie。
默认情况下,每个django应用程序的cookie名称为csrftoken

您需要使用CSRF_COOKIE_NAME设置(在settings.py中)更改至少一个cookie的名称。在

然后,您的同事可以使用以下AJAX调用检索cookie:

// using jQuery
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;
}
var csrftoken = getCookie('name_of_your_token');

对于更复杂的用法,请查看文档:https://docs.djangoproject.com/en/2.0/ref/csrf/


类似的情况:Multiple Django sites on the same domain - CSRF fails

这个问题在我看来是XY problem的一个例子。在下面的课文中,我将回到我的主张并解释它。在

OP使用Django REST框架编写了一个restapi。忽略这些信息最初会导致注意力非常低。包括这些信息之后,事情变得更清楚了。在

让我们首先回顾一下restapi的一些基本知识。restapi与语言无关。它不关心客户机是用哪种语言编写的,客户机也不关心API是用哪种语言编写的。restapi可以通过不同的方式访问(使用):从命令行使用curl;从用任何编程语言编写的脚本;从使用(很可能)JavaScript(或JavaScript框架)的浏览器。在

由于有两个网站在使用API,OP希望为他们提供对API的访问。出现的障碍是CSRF(跨站点请求伪造)。
Django使用CSRF令牌实现了CSRF保护。这意味着我们保护我们的网站不受来自其他网站的请求,在那里通常可以将表格张贴到我们的网站上。在

在实际情况下,客户机是两个不同的网站托管在不同的域,因此来自他们的请求来自不同的网站。运营商真正想知道的是:
“如何授予或限制访问使用我的API的其他网站?”
而不是:
“如何处理CSRF问题?”

Django REST Framwork的官方文档有一个专门针对这个问题的页面:
Working with AJAX, CSRF & CORS

以下是CORS部分:

Cross-Origin Resource Sharing is a mechanism for allowing clients to interact with APIs that are hosted on a different domain. CORS works by requiring the server to include a specific set of headers that allow a browser to determine if and when cross-domain requests should be allowed.

The best way to deal with CORS in REST framework is to add the required response headers in middleware. This ensures that CORS is supported transparently, without having to change any behavior in your views.

Otto Yiu maintains the django-cors-headers package, which is known to work correctly with REST framework APIs.

我要强调第一句话:

Cross-Origin Resource Sharing is a mechanism for allowing clients to interact with APIs that are hosted on a different domain.

确实如此。OP希望允许客户端与托管在不同域上的API进行交互。
最后一句话建议使用django-cors-headers,这是问题的解决方案。
关于该应用程序使用的所有详细信息可以在其文档中找到。在

谢谢@cezar和@johnmutafis,我读了CORS的文档:

Cross-Origin Resource Sharing is a mechanism for allowing clients to interact with APIs that are hosted on a different domain. CORS works by requiring the server to include a specific set of headers that allow a browser to determine if and when cross-domain requests should be allowed.

然后我安装了django-cors-headers,并使用它。在

我设置CORS_ORIGIN_WHITELIST

CORS_ORIGIN_WHITELIST = (
    'http://10.10.10.102:8000', # normal user site
    'http://10.10.10.102:8080', # admin backend site
)

现在它工作得很好。在

再次感谢你。在

相关问题 更多 >