如何在一个浏览器中处理两个具有一个后端 CSRF 问题的网站?
How to deal with two websites with one backend CSRF issue in one browser?
如何在一个浏览器中处理独立首页和管理网站的CSRF问题?
我们为它写了一个主页前端和一个管理网站前端(有两个前端),前端使用JavaScript。
由于这两个站点都很大,我们将它们作为虚拟主机放在 Nginx 中。他们是两个网站。我使用 Python (Django) 编写 one 后端,两个站点调用一个后端。
主页使用Nginx的default.conf
,管理网站使用vhosts/admin.conf
.
这是测试域:
http://www.ajw123.xyz
作为首页。
http://admin.ajw123.xyz
作为管理网站。
我的问题是在浏览器中使用账号登录首页时:
然后我用账号登录admin网站(或其他账号),抛出CSRF Token Error:
你看 csrftoken
都是:
csrftoken=L5bRGEXDvW9dJaXsanLlMTOrxxGpxJCw6vji1zQtjzYrskOq0FBjQtfkhvFKFDmj;
预览中:
CSRF Failed: CSRF token missing or incorrect.
我使用 Django-Rest-Framework 作为 rest API,我们的前端同事写了两个站点(一个是普通用户的前端和后端站点,另一个是管理员的后端站点),两者都使用我的 rest API。
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/
类似案例:
感谢@cezar 和@JohnMoutafis,我阅读了 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
)
现在可以正常使用了。
再次感谢。
这个问题在我看来是XY problem的一个例子。在接下来的文字中,我将回到我的主张并加以解释。
OP 使用 Django REST Framework 编写了 REST API。忽略此信息最初导致的关注度非常低。包括这些信息后,事情变得更加清晰。
让我们首先回顾一下有关 REST API 的一些基础知识。 REST API 与语言无关。它不关心客户端是用哪种语言编写的,客户端也不关心 API 是用哪种语言编写的。可以通过不同的方式访问(使用)REST API:从命令行使用 curl
;来自以任何编程语言编写的脚本;来自使用(最有可能)JavaScript(或 JavaScript 框架)的浏览器。
由于有两个网站使用 API,OP 希望为他们提供访问 API 的权限。出现的障碍是CSRF(跨站请求伪造)。
Django 使用 CSRF 令牌实现了 CSRF 保护。这意味着我们保护我们的网站免受来自其他网站的请求,通常可以将表格张贴到我们的网站。
在实际情况下,客户端是托管在不同域上的两个不同网站,因此来自它们的请求来自不同的站点。 OP 真正想知道的是:
“如何授予或限制访问其他使用我的 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
也就是问题的解决方法
有关应用程序使用的所有详细信息,请参阅其文档。
如何在一个浏览器中处理独立首页和管理网站的CSRF问题?
我们为它写了一个主页前端和一个管理网站前端(有两个前端),前端使用JavaScript。
由于这两个站点都很大,我们将它们作为虚拟主机放在 Nginx 中。他们是两个网站。我使用 Python (Django) 编写 one 后端,两个站点调用一个后端。
主页使用Nginx的default.conf
,管理网站使用vhosts/admin.conf
.
这是测试域:
http://www.ajw123.xyz
作为首页。
http://admin.ajw123.xyz
作为管理网站。
我的问题是在浏览器中使用账号登录首页时:
然后我用账号登录admin网站(或其他账号),抛出CSRF Token Error:
你看 csrftoken
都是:
csrftoken=L5bRGEXDvW9dJaXsanLlMTOrxxGpxJCw6vji1zQtjzYrskOq0FBjQtfkhvFKFDmj;
预览中:
CSRF Failed: CSRF token missing or incorrect.
我使用 Django-Rest-Framework 作为 rest API,我们的前端同事写了两个站点(一个是普通用户的前端和后端站点,另一个是管理员的后端站点),两者都使用我的 rest API。
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/
类似案例:
感谢@cezar 和@JohnMoutafis,我阅读了 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
)
现在可以正常使用了。
再次感谢。
这个问题在我看来是XY problem的一个例子。在接下来的文字中,我将回到我的主张并加以解释。
OP 使用 Django REST Framework 编写了 REST API。忽略此信息最初导致的关注度非常低。包括这些信息后,事情变得更加清晰。
让我们首先回顾一下有关 REST API 的一些基础知识。 REST API 与语言无关。它不关心客户端是用哪种语言编写的,客户端也不关心 API 是用哪种语言编写的。可以通过不同的方式访问(使用)REST API:从命令行使用 curl
;来自以任何编程语言编写的脚本;来自使用(最有可能)JavaScript(或 JavaScript 框架)的浏览器。
由于有两个网站使用 API,OP 希望为他们提供访问 API 的权限。出现的障碍是CSRF(跨站请求伪造)。
Django 使用 CSRF 令牌实现了 CSRF 保护。这意味着我们保护我们的网站免受来自其他网站的请求,通常可以将表格张贴到我们的网站。
在实际情况下,客户端是托管在不同域上的两个不同网站,因此来自它们的请求来自不同的站点。 OP 真正想知道的是:
“如何授予或限制访问其他使用我的 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
也就是问题的解决方法
有关应用程序使用的所有详细信息,请参阅其文档。