Django在后端和前端分离时的CSRF问题

19 投票
3 回答
3401 浏览
提问于 2025-04-17 06:01

在网上搜索后,人们通常会处理这种情况——前端是由 Django 的视图函数生成的,这个函数可以把 CSRF 令牌的 cookie 发送给用户。当用户通过 AJAX 向服务器发送请求时,可以重写 ajaxSend 的行为,把 CSRF 令牌发送到服务器。

但是,我的情况是前端和后端完全分开,也就是说,我的前端在一个专门的服务器上运行 nginx,而我只有一个 HTML 页面,通过 hashbang 提供所有不同的页面。我的后端在不同的服务器上,使用不同的域名,在这种情况下,客户端怎么才能获取到 CSRF cookie 呢?我的后端只提供返回 JSON 的 API。

谢谢。

3 个回答

-1

如果你查看CRSF令牌的源代码,你会发现csrf_middleware的作用就是检查cookie和post值是否匹配。你只需要把post值发送回你的服务器,因为cookie应该已经通过ajax设置好了。再看一下模板标签的源代码,你会发现它只是从上下文中取出变量。你可以通过从上下文中提取这个变量,把它放到你的响应中,或者直接调用上下文处理器。现在你只需要把它作为POST变量crsf_token发送回去。

-1

假设前端的域名是 frontend.example.com,后端的域名是 backend.example.com。(如果你使用的是像 Django 这样的框架)

你可以通过两种方式来增强安全性,也就是 CSRF 保护或 CORS。

关于 CORS,

pip install django-cors-headers

然后需要把这个配置添加到 INSTALLED_APPS 和 MIDDLEWARE_CLASSES 中,并把前端的域名添加到 CORS_ORIGIN_WHITELIST。

CORS_ORIGIN_WHITELIST = (
    'frontend.example.com'
)

CORS 会阻止来自其他域名的任何 HTTP 请求,只有 frontend.example.com 的请求是被允许的。


关于 CSRF,

CSRF_COOKIE_DOMAIN = ".mydomain.com"

如果你在使用 Angular 应用,可以按照下面的方式操作,

$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
$httpProvider.defaults.withCredentials = true;

然后在发起 HTTP 请求时添加一些头信息。

headers : {
    "x-csrftoken" : $cookies.csrftoken
}
8

这篇文章虽然有点旧,但对于那些仍然在这里寻找答案的人来说:对于客户端和服务器的设置,比如本地桌面和移动客户端(还有像楼主提到的那种单独的前端),最好使用Django Rest Framework的令牌认证。链接

撰写回答