如何在不同主机的axios中使用Django的CSRF保护?
How to use Django's CSRF protection in axios for different host?
我正在将 ReactJS 项目作为前端,将 Django 作为后端,并且在 CSRF 保护方面遇到了麻烦!
我正在使用 Django CORS headers,并且我已正确完成所有设置。只要我有本地主机来访问前端和后端,它就可以工作。我的前端 运行 在 localhost:3006 上,后端我们 运行 在 localhost:8899 端口上。所以前端正在设置 csrftoken
cookie 并使用 post 请求发送它。
我将 axios.create()
与 withCredentials = true
一起使用,效果很好。现在,当我的 co-worker 与他的系统 运行 相同的前端代码时,尝试连接到我机器上 运行 的后端时,他收到 403 csrf cookie not found!此时,他是 运行 他在 localhost:3006
上的前端,他自己的本地主机并连接到 my-ip:8899
的后端。所以我相信当我们有 www.example.com
服务前端和 api.example.com
服务后端时,我们也会在生产中遇到这个问题,因为前端主机的 cookie 不会发送到 api 主机!
我的 cors header 在 django 中的设置,
# Origin white list
CORS_ORIGIN_WHITELIST = [
'http://localhost',
'http://127.0.0.1',
'http://192.168.1.165',
'http://192.168.1.165:3006',
]
CORS_EXPOSE_HEADERS = (
'Access-Control-Allow-Origin: *',
)
# Allowed methods
CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
)
# Allowed headers
CORS_ALLOW_HEADERS = (
'accept',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'X-tz',
'x-tz',
'x-requested-with',
)
# # CSRF COOKIE NAME
CSRF_COOKIE_NAME = "csrftoken"
# To allow default credentials
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
我的 Axios 创建代码是,
let tz = "UTC";
try {
tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
} catch (e) {
consoleError(e);
}
const API = axios.create({
baseURL: process.env.REACT_APP_API_HOST,
timeout: 30000,
withCredentials: true,
xsrfCookieName: CSRF_COOKIE_NAME,
xsrfHeaderName: "X-CSRFToken",
headers: {'X-tz': tz}
});
正如我所说,如果我使用 localhost/IP 和端口从我的机器连接到我的机器,它可以工作,但是当我的 co-worker 试图从他的 localhost/IP 连接时我的 ip-backend 前端不允许他在没有 CSRF cookie 的情况下发出 POST 请求!我不想用装饰器绕过 CSRF 的 Django 安全性。那么谁能告诉我我做错了什么?
CSRF 通过将 cookie 中的令牌与 X-CSRFToken header(或表单数据)中的令牌进行匹配来工作。您的 axios 请求必须发送 both.
它正在 X-CSRFToken 中发送令牌。但它没有将 cookie 发送到 api.yourhost.com,因为 cookie 是为域 www.yourhost.com 设置的。这是 Django 中的默认值。
将 CSRF_COOKIE_DOMAIN
更改为以 .
开头的 eTLD+1 域,即 .yourhost.com,以便将其发送到您的每个子域,包括 api.yourhost.com .
现在在您的测试场景中,这不起作用,因为您同事的前端设置的 cookie 是针对本地主机的,而 axios 请求是针对您的 ip。除了让您的 co-worker 也从您的 ip 获取前端外,没有其他解决方案。
我正在将 ReactJS 项目作为前端,将 Django 作为后端,并且在 CSRF 保护方面遇到了麻烦!
我正在使用 Django CORS headers,并且我已正确完成所有设置。只要我有本地主机来访问前端和后端,它就可以工作。我的前端 运行 在 localhost:3006 上,后端我们 运行 在 localhost:8899 端口上。所以前端正在设置 csrftoken
cookie 并使用 post 请求发送它。
我将 axios.create()
与 withCredentials = true
一起使用,效果很好。现在,当我的 co-worker 与他的系统 运行 相同的前端代码时,尝试连接到我机器上 运行 的后端时,他收到 403 csrf cookie not found!此时,他是 运行 他在 localhost:3006
上的前端,他自己的本地主机并连接到 my-ip:8899
的后端。所以我相信当我们有 www.example.com
服务前端和 api.example.com
服务后端时,我们也会在生产中遇到这个问题,因为前端主机的 cookie 不会发送到 api 主机!
我的 cors header 在 django 中的设置,
# Origin white list
CORS_ORIGIN_WHITELIST = [
'http://localhost',
'http://127.0.0.1',
'http://192.168.1.165',
'http://192.168.1.165:3006',
]
CORS_EXPOSE_HEADERS = (
'Access-Control-Allow-Origin: *',
)
# Allowed methods
CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
)
# Allowed headers
CORS_ALLOW_HEADERS = (
'accept',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'X-tz',
'x-tz',
'x-requested-with',
)
# # CSRF COOKIE NAME
CSRF_COOKIE_NAME = "csrftoken"
# To allow default credentials
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
我的 Axios 创建代码是,
let tz = "UTC";
try {
tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
} catch (e) {
consoleError(e);
}
const API = axios.create({
baseURL: process.env.REACT_APP_API_HOST,
timeout: 30000,
withCredentials: true,
xsrfCookieName: CSRF_COOKIE_NAME,
xsrfHeaderName: "X-CSRFToken",
headers: {'X-tz': tz}
});
正如我所说,如果我使用 localhost/IP 和端口从我的机器连接到我的机器,它可以工作,但是当我的 co-worker 试图从他的 localhost/IP 连接时我的 ip-backend 前端不允许他在没有 CSRF cookie 的情况下发出 POST 请求!我不想用装饰器绕过 CSRF 的 Django 安全性。那么谁能告诉我我做错了什么?
CSRF 通过将 cookie 中的令牌与 X-CSRFToken header(或表单数据)中的令牌进行匹配来工作。您的 axios 请求必须发送 both.
它正在 X-CSRFToken 中发送令牌。但它没有将 cookie 发送到 api.yourhost.com,因为 cookie 是为域 www.yourhost.com 设置的。这是 Django 中的默认值。
将 CSRF_COOKIE_DOMAIN
更改为以 .
开头的 eTLD+1 域,即 .yourhost.com,以便将其发送到您的每个子域,包括 api.yourhost.com .
现在在您的测试场景中,这不起作用,因为您同事的前端设置的 cookie 是针对本地主机的,而 axios 请求是针对您的 ip。除了让您的 co-worker 也从您的 ip 获取前端外,没有其他解决方案。