跨域 POST 请求的 CSRF 验证在生产中失败
Posted
技术标签:
【中文标题】跨域 POST 请求的 CSRF 验证在生产中失败【英文标题】:CSRF Verification fails in production for Cross Domain POST request 【发布时间】:2019-09-14 11:08:47 【问题描述】:HTTP_X_CSRFTOKEN 标头与 csrftoken cookie 中的内容不匹配。
如何检查 cookie? Set-Cookie 不显示在跨域请求的响应标头中。
我已经按照以下中的说明进行操作:
CSRF with Django, React+Redux using Axios
有趣的是,我发现“X-CSRFTOKEN”在服务器请求标头上转换为“HTTP_X_CSRFTOKEN”。
在 localhost 下的开发环境中工作正常(尽管我使用 2 个不同的端口 - 一个用于 django,另一个用于我的前端)。
更新:
似乎没有为跨域请求正确设置 csrktoken cookie(尽管浏览器在请求标头中显示它),因此 X-CSRFTOKEN 没有被发送。
我最终添加了一个 API 调用,以使用 GET 请求返回当前 csrftoken,然后使用 X-CSRFTOKEN 标头将其发回。
【问题讨论】:
【参考方案1】:您首先没有提到您是如何从服务器获取csrftoken
的,所以我假设它已经存在于您的浏览器中。
除了X-CSRFToken
标头,还使用withCredentials: true
在请求中包含cookie。
我正在使用 js-cookie
库从 cookie 中获取 csrftoken
。
import Cookies from 'js-cookie';
axios(
url: 'http://localhost:8000/graphql',
method: 'post',
withCredentials: true,
data:
query: `
// Your query here
`
,
headers:
"X-CSRFToken": Cookies.get('csrftoken')
)
如果您使用的是django-cors-headers
,请将CORS_ALLOW_CREDENTIALS = True
添加到您的settings.py
。否则,cookie 将不被接受。
【讨论】:
【参考方案2】:您必须通过 CORS Access-Control-Expose-Headers
指令使 X-CSRFTOKEN
标头可访问。示例:
Access-Control-Expose-Headers: X-CSRFTOKEN
此标头必须由您的 API 或 Web 服务器设置,以便浏览器在 CORS 预检请求期间看到它。
【讨论】:
django-cors-headers 这样做。实际上正在发送标头。不是 cookie。尽管显示在 chrome devtools 的请求标头中。以上是关于跨域 POST 请求的 CSRF 验证在生产中失败的主要内容,如果未能解决你的问题,请参考以下文章
CSRF 验证失败 - 当主机安全时,Referer 不安全
iPhone POST 到 Django 并获得 CSRF 验证失败