在单页应用程序中使用 Cookie 到标头的 CSRF 令牌 什么是 CSRF 攻击?CORS 能保护我免受 CSRF 攻击吗?那么什么能保护我免受 CSRF 攻击?在单页应用程序中使用 Cookie 来获取 CSRF 令牌 为什么我喜欢在 SPA 的 Cookie 中获取 CSRF 令牌 重要配置说明 未来:SameSite Cookie

2025-06-07

在单页应用程序中使用 Cookie-to-Header CSRF 令牌

什么是 CSRF 攻击?

CORS 能保护我免受 CSRF 攻击吗?

那么什么可以保护我免受 CSRF 攻击?

在单页应用程序中使用 Cookies 作为 CSRF 令牌

为什么我喜欢在 SPA 的 Cookie 中获取 CSRF 令牌

重要配置说明

未来:SameSite Cookies

跨站请求伪造 (CSRF) 攻击向量常常被误解。今天,我们将深入理解 CSRF,并探讨为什么基于 Cookie 的 CSRF 令牌是单页应用程序 (SPA) 的理想选择。


如果您喜欢本教程,请给予💓、🦄或🔖并考虑:

📬 注册我的免费每周开发者简报
🎥 订阅我的免费 YouTube 开发者频道


什么是 CSRF 攻击?

CSRF 攻击是指攻击者的网站能够使用已登录用户的 Cookie 成功向您的网站提交请求。这种攻击之所以可能发生,是因为浏览器会“主动”地将 Cookie 添加到任何向您网站发出的请求中,无论该请求来自何处。

让我们来看一下 CSRF 攻击的具体表现。

用户登录您的网站并正常进行交互

用户访问我们的网站,并向我们的服务器提交他们的电子邮件地址和密码。我们的服务器验证这些信息,并向sessionId客户端发送一个 cookie。客户端现在开始向后端发出请求,并sessionId在请求过程中发送 cookie。

用户登录流程

用户导航到攻击者的网站,该网站向您的后端发出 POST 请求

在某个时刻,用户会导航到攻击者的网站(假设是attacker.com……听起来很吓人,对吧?)。攻击者对我们的网站足够了解,知道我们有一个/profile接受post请求的端点,并且知道如果用户new_email向该端点发送邮件,该用户的账户邮箱就会被更改。

因此,当用户访问 attack.com 时,该网站会向我们网站的/profile端点发送一个 post 请求。浏览器会说:“哦!我有这个网站的 cookie,请允许我把它附加到这个请求中!”

袭击

当然,这是我们最不希望发生的事情,因为攻击者现在已经伪装成登录用户并更改了该用户的电子邮件地址。攻击者现在已经控制了该帐户——在我们的网站上请求重置密码会将重置链接发送到攻击者的电子邮件地址,这样他们就成功了!

CORS 能保护我免受 CSRF 攻击吗?

跨域资源共享 (CORS)无法保护您免受 CSRF 攻击。CORS 是一种基于标头的机制,用于告知客户端哪些来源可以访问服务器上的资源。

假设您的前端位于https://www.yoursite.com,后端位于https://api.yoursite.com。在响应任何请求时,您可以将后端配置为“我希望访问我的资源的唯一来源是https://www.yoursite.com”。

Access-Control-Allow-Origin: https://www.yoursite.com
Enter fullscreen mode Exit fullscreen mode

这确实有效!例如,如果attacker.com尝试get从后端受 CORS 保护的 API 端点获取数据,请求将会失败,因为浏览器不允许attacker.com网站查看该请求的响应。但这并不是CSRF攻击——攻击者不需要查看 POST 请求的响应;损害在请求发出时就已经造成了!

TL;DR: CORS 保护非常重要,但它对 CSRF 攻击无能为力。

那么什么可以保护我免受 CSRF 攻击?

防御 CSRF 攻击的方法是使用CSRF 令牌。这是由服务器生成并以某种方式提供给客户端的令牌。然而,CSRF 令牌和会话 Cookie 之间的最大区别在于,客户端每次向后端发出 POST 请求时,都需要将 CSRF 令牌放在非 Cookie 标头(例如XSRF-TOKEN)中。浏览器不会自动生成此XSRF-TOKEN标头,因此仅通过向端点发送数据就无法再成功发起攻击/profile

在单页应用程序中使用 Cookies 作为 CSRF 令牌

等等?Cookie 正是我们陷入这种困境的根本原因,那么我们该如何使用 Cookie 来保护 CSRF 安全呢?

需要记住的是,当我们向后端发出 POST 请求时,后端不希望 CSRF 令牌出现在Cookie请求头中。它希望 CSRF 令牌作为自己的请求头。攻击者根本无法添加该 CSRF 专用的请求头,浏览器当然也不会帮他们添加。

使用 Cookie 到标头 CSRF 令牌

因此,如果我们在上面的图表中添加一个 CSRF 令牌,我们将得到以下结果。

csrf 流程

如果攻击者尝试发起 POST 请求,他们无法提供XSRF-TOKEN请求头。即使我们的浏览器自动返回XSRF-TOKENCookie,我们的后端也根本不会去寻找它。

攻击企图

为什么我喜欢在 SPA 的 Cookie 中获取 CSRF 令牌

后端可以通过几种不同的方式为我们的 SPA 提供服务:在 cookie 中、在自定义响应标头中以及在响应正文中。

我更喜欢 cookie 方法的主要原因是,我们不需要为浏览器执行任何特殊操作来保存这些信息:当服务器发送 cookie 时,浏览器会自动保存它,直到 cookie 过期(或用户删除)。这意味着 cookieXSRF-TOKEN会一直在那里等待,直到我们需要它为止。但是,如果服务器在自定义标头或响应主体中向我们发送 CSRF 令牌,我们就必须在 JavaScript 代码中主动处理该响应信息。我们可以将其推送到应用状态或设置一个新的 cookie,但我们必须主动执行某些操作。

还有一个额外的好处,一些 HTTP 请求客户端axios会自动在我们的浏览器中查找XSRF-TOKENCookie,并在发送请求时将其转换为自定义标头!这意味着我们在将数据发布到受 CSRF 保护的端点时甚至不需要做任何特别的事情。

重要配置说明

当采用 CSRF-in-cookie 路线时,存在一些“陷阱”。

首先,您的 SPA 需要位于同一域名。例如,如果您的后端位于 ,api.yoursite.com而您的 SPA 位于www.yoursite.com,那么只需DOMAIN在 Cookie 上添加一个额外属性即可。但是,如果您的后端位于 ,api.yoursite.com而您的 SPA 位于www.othersite.com,那么您的前端将无法读取XSRF-TOKENCookie,您需要使用不同的路由来处理 CSRF 令牌。

接下来,唯一可行的方法是我们的​​ JavaScript 代码能够访问该 Cookie。这意味着我们的服务器无法将其设置XSRF-TOKEN为 HTTPOnly(HTTPOnly 意味着我们的客户端/浏览器可以将 Cookie 发送回服务器,但我们的 JavaScript 代码无法看到它)。

其中一个配置细节axios是,它会专门查找XSRF-TOKENCookie,如果找到,就会将令牌作为X-XSRF-TOKEN标头发送回去。这些都是可配置的,但您需要确保配置正确,否则您会疑惑它为什么不起作用。

未来:SameSite Cookies

这一切都很好,但 CSRF 保护实际上只是针对某些奇怪的浏览器行为(自动将 Cookie 附加到任何发往特定来源的请求)的修复。设置SameSitecookie 属性可以解决这个问题:如果浏览器检测到一个SameSite属性设置为Lax或 的Cookie Strict,它就不会向服务器发送 POST 请求,除非该请求来自同一站点(相同的协议 + 域名,但子域​​名可以不同)。

一旦它得到普遍支持,这将是一件好事——cookieSameSite属性相对较新。浏览器必须理解SameSitecookie 的含义,如果有人使用理解 cookie 含义的旧版浏览器SameSite,那么该用户将容易受到 CSRF 攻击。为了确保使用这种SameSite方法的可靠性,我们需要确保它SameSite在所有浏览器中都得到普遍支持。我不确定什么时候会实现,但目前我们只能使用 CSRF 令牌保护!

文章来源:https://dev.to/nas5w/using-a-cookie-to-header-csrf-token-in-single-page-applications-ngh
PREV
在 React 中使用自定义 useLocalStorage Hook 的本地存储 我们的方法 创建 Hook 测试我们的新 Hook
NEXT
使用 useContext 在 React 中切换亮/暗主题演示和完整代码深入代码