如何在一个浏览器中处理独立的主页和管理网站CSRF问题?
我们已经为它创建了一个主页网站前端和一个管理网站前端(有两个前端),在前端使用JavaScript。 因为两个站点都很大,所以我们将它们作为vhost放在Nginx中。他们是两个网站。我使用Python(Django)编写一个后端,两个站点都调用一个后端。
主页使用Nginx的default.conf
,管理网站使用vhosts/admin.conf
。
这是测试域:
http://www.ajw123.xyz
作为主页。
http://admin.ajw123.xyz
作为管理员网站。
我的麻烦是当我在浏览器的主页上使用帐户登录时:
然后我使用该帐户登录管理网站(或其他帐户),抛出CSRF令牌错误:
您看到csrftoken
都是:
csrftoken=L5bRGEXDvW9dJaXsanLlMTOrxxGpxJCw6vji1zQtjzYrskOq0FBjQtfkhvFKFDmj;
在预览中:
CSRF失败:CSRF令牌丢失或不正确。
我将Django-Rest-Framework用于其他API,我们的前端同事编写两个站点(一个是普通用户前端和后端站点,另一个是管理员的后端站点),两者都使用我的其余API
答案 0 :(得分:3)
问题在于我在XY problem的一个例子。在下面的文字中,我将回到我的主张并解释它。
OP使用Django REST Framework编写了一个REST API。最初省略这些信息导致很少关注。在包含这些信息后,事情变得更加清晰。
让我们首先回顾一些关于REST API的基础知识。 REST API与语言无关。它并不关心客户编写的语言,而且客户也不关心API编写的语言。可以通过不同方式访问(使用)REST API:从命令行使用curl
;来自用任何编程语言编写的脚本;来自使用(最有可能)JavaScript(或JavaScript框架)的浏览器。
由于有两个网站在使用API,因此OP希望为他们提供对API的访问权限。出现的障碍是CSRF(Cross Site Request Forgery) Django使用CSRF令牌实施了CSRF保护。这意味着我们保护我们的网站免受来自其他网站的请求,通常可以将表格发布到我们的网站。
在实际情况下,客户端是托管在不同域上的两个不同网站,因此来自它们的请求来自不同的站点。 OP真正想知道的是:
"如何授予或限制访问使用我的API的其他网站?"
而不是:
"如何处理CSRF问题?"
Django REST Framwork的官方文档有一个专门讨论这个问题的页面:
Working with AJAX, CSRF & CORS
这是CORS的部分:
跨源资源共享是一种允许客户端与托管在不同域上的API进行交互的机制。 CORS的工作原理是要求服务器包含一组特定的标头,允许浏览器确定是否以及何时允许跨域请求。
在REST框架中处理CORS的最佳方法是在中间件中添加所需的响应头。这可确保透明地支持CORS,而无需更改视图中的任何行为。
Otto Yiu维护着django-cors-headers包,已知它可以正常使用REST框架API。
我会强调第一句话:
跨源资源共享是一种允许客户端与托管在不同域上的API进行交互的机制。
确实如此。 OP希望允许客户端与托管在不同域上的API进行交互
最后一句建议使用django-cors-headers
,这是问题的解决方案
有关应用程序使用的所有详细信息,请参阅其文档。
答案 1 :(得分:2)
CSRF令牌本质上是一个可检索的cookie
默认情况下,对于每个django应用,此Cookie的名称为csrftoken
。
您需要使用CSRF_COOKIE_NAME
设置更改至少一个Cookie的名称(在settings.py
中)。
然后你的同事可以通过以下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');
有关更复杂的用途,请查看文档:{{3}}
<小时/> 类似的案例:https://docs.djangoproject.com/en/2.0/ref/csrf/
答案 2 :(得分:2)
感谢@cezar和@JohnMoutafis,我阅读了CORS的文档:
跨源资源共享是一种允许客户端与托管在不同域上的API进行交互的机制。 CORS的工作原理是要求服务器包含一组特定的标头,允许浏览器确定是否以及何时应允许跨域请求。
然后我安装了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
)
现在它运作正常。
再次感谢你。