Spring 文档状态:
我们的建议是对普通用户可以通过浏览器处理的任何请求使用 CSRF 保护。如果您只创建非浏览器客户端使用的服务,您可能希望禁用 CSRF 保护。
我有兴趣为什么?为什么在构建仅客户端是非浏览器的服务时禁用 CSRF 保护是可以的,但在服务与浏览器客户端对话时应该启用它?
Spring 文档状态:
我们的建议是对普通用户可以通过浏览器处理的任何请求使用 CSRF 保护。如果您只创建非浏览器客户端使用的服务,您可能希望禁用 CSRF 保护。
我有兴趣为什么?为什么在构建仅客户端是非浏览器的服务时禁用 CSRF 保护是可以的,但在服务与浏览器客户端对话时应该启用它?
归结为 CSRF 是对浏览器的攻击,因此如果您的服务仅由非浏览器使用,则使用反 CSRF 防御是没有意义的,这可能很昂贵,因此可能值得禁用。
当浏览器与服务器交互时,每个请求都是单独进来的,所以如果服务想要进行身份验证,它需要添加一些方案来连接请求(以避免必须让用户对每个请求进行身份验证)。一种常见的方法是为用户的浏览器设置一个cookie,当浏览器每次后续请求时自动发送该cookie)。
与有保护的对比
然而,恶意脚本可以向服务器发出请求,并且浏览器将有助于包含 cookie。但是,脚本将无法直接访问 cookie(假设指定了正确的 cookie 选项)。因此,针对 CSRF 的保护措施是在请求中与 cookie 分开(即表单上的隐藏字段),以验证请求来自正确的表单,而不是脚本。
CSRF 依赖于浏览器自动发送带有跨站点请求的 cookie,因为 Javascript/攻击者的站点无权访问 cookie。
CSRF 保护依赖于服务器将浏览器自动发送的内容(cookie)与表单中的内容(令牌)相关联。
非浏览器客户端将同时控制令牌和 cookie,因此可以使它们匹配(如果它可以完全获取 cookie)。因此,如果服务永远不会被浏览器访问,那么复杂的 CSRF 保护就没有意义了。
TL/DR - CSRF 本质上是一种浏览器攻击,因此只有浏览器可能访问的服务才需要对其进行保护。
因为威胁模型不同。
在浏览器上下文中,我们期望浏览器用户应该能够导航到任意网页,而不必担心它会代表用户进行未经授权的操作。尽管网页可能会使用用户预先存在的授权令牌(即 cookie)发起对任意外部资源的获取请求,并且对此类请求的参数有一定的有限控制,尽管它们通常无法看到响应的内容。CSRF 保护旨在防范这种威胁,攻击者可以代表某人发起或多或少的任意请求,但通常看不到响应。
在浏览器之外的类似情况下,威胁模型是不同的。本机应用程序可以打开到任意主机的任意套接字连接,完全控制发起的请求,并且始终可以看到来自服务器的完整响应。“如果我运行一个可能代表我发起未经授权的请求的应用程序怎么办?”类似问题的答案。成为著名的医生笑话(“好吧,不要那样做”)的妙语。正如Raymond Chen 喜欢说的,你已经在密闭舱口的另一边了。本机应用程序可以轻松绕过任何 CSRF 保护方案;它只会相当于安全剧院。
也就是说,请注意您引用的有关 CSRF 保护的建议是如何措辞的:它仅表明您可能希望在您的端点永远无法在浏览器上下文中使用时禁用它。只要 Web 浏览器完全可以向它发起授权请求(无论您是否打算将其用于此类用途),CSRF 保护就可能提供一些价值,即使本机应用程序可以轻松绕过它。