我知道这个问题已经被问过好几次了,但我从来没有找到一个明确的解决方案。如何保护web应用程序免受CSRF攻击?
我目前有两个域,frontend.com
和backend.com
。后端使用flask-wtf
创建会话(存储在前端浏览器的cookie中),并在响应头中返回CSRF token
。
我能够获得令牌,并发送带有令牌附加到报头的请求。然而,我注意到饼干从来没有凝固过。因此,我假设这就是为什么我得到一个错误的400: Bad Request
。经过不断的阅读和研究,我几乎确信它意味着在相同的域中使用。.
我目前的技术栈是:
DNS: Cloudflare
托管:Heroku
- 反应客户 Python (Flask) API
我看不出CSRF令牌如何在这种情况下使用,除非我错过了对它工作至关重要的东西。
也就是说,根据我的情况,在跨域设置中解决CSRF保护的最佳方法是什么?
此外,这一切都在我的本地开发环境中工作。我不知道为什么它在生产中突然停止工作了。
一个示例请求看起来像这样:
const headers = {
'Content-Type': 'application/json',
'X-CSRF-Token': csrfToken
};
...
const handleFormSubmission = async e => {
e.preventDefault();
await axios.post('https://backend.com/add-results', { tokenId: tokenId }, { withCredentials: true, headers: headers })
}
后端有以下设置:
...
CORS(app, origins=["https://www.frontend.com"], expose_headers=["Content-Type", "X-CSRFToken"], supports_credentials=True)
...
app.config['SESSION_COOKIE_SECURE'] = True
app.config['SESSION_COOKIE_HTTPONLY'] = True
app.config['REMEMBER_COOKIE_SECURE'] = True
app.config['REMEMBER_COOKIE_HTTPONLY'] = True
app.config['SESSION_COOKIE_SAMESITE'] = 'Lax'
这是非常奇怪的,因为这工作在开发环境
您实际上似乎有一个工作CSRF保护到位。你说:
我能够获得令牌并发送带有令牌附加到报头的请求。然而,我注意到饼干从来没有设置过。
所以你的问题似乎是你没有得到会话cookie,这是另一回事。
这是跨域请求的典型问题。默认情况下,由于安全原因,浏览器不会将cookie发送到另一个域。您要么需要通过Access-Control-*
头启用CORS,要么使用替代令牌存储机制而不是cookie(例如Web storage)。
我非常推荐Api Security in Action这本书,它在第5章讨论了这个主题(特别是5.1和5.2的Web存储)