我正在编写一个 Django RESTful API 来支持 iOS 应用程序,并且每当我编写处理 POST 请求的方法时,我都会遇到 Django 的 CSRF 保护。
我的理解是 iOS 管理的 cookie 不被应用程序共享,这意味着我的会话 cookie 是安全的,没有其他应用程序可以使用它们。这是真的?如果是这样,我可以将我所有的 API 函数标记为 CSRF-exempt 吗?
这不是 CSRF 保护的目的。CSRF 保护是为了防止将数据直接发布到您的站点。换句话说,客户端实际上必须通过批准的路径发布,即查看表单页面,填写它,提交数据。
API 几乎排除了 CSRF,因为它的全部目的通常是允许第 3 方实体访问和操作您站点上的数据(CSRF 中的“跨站点”)。所以,是的,我认为通常任何 API 视图都应该是 CSRF 豁免的。但是,您仍应遵循最佳实践并保护每个通过某种形式的身份验证(例如 OAuth)实际进行更改的 API 端点。
CSRF 攻击依赖于将所有请求隐式发送到特定域的 cookie。如果您的 API 端点不允许基于 cookie 的身份验证,那么您应该很好。
即使您确实使用了基于 cookie 的身份验证,您的 cookie 也是安全的,因为iOS 应用程序不共享 cookie。但是,除非您通过要求不寻常的用户代理标头故意阻止 Web 浏览器,否则另一方可能会构建使用您的 API 的基于浏览器的应用程序,如果您的 API 支持基于 cookie 的身份验证并且不支持,那么该应用程序将容易受到 CSRF 攻击'不应用 CSRF 保护。
如果您还使用 API 来支持网站,它们确实适用。
在这种情况下,您仍然需要某种形式的 CSRF 保护,以防止有人在其他站点中嵌入请求,从而对经过身份验证的用户帐户产生偷渡效应。
Chrome 似乎默认拒绝跨域 POST 请求(其他浏览器可能没有那么严格),但允许跨域 GET 请求,因此您必须确保 API 中的任何 GET 请求都没有副作用。
这个当前接受的答案(2012 年 5 月)大部分是正确的,除非您使用基于会话的身份验证。还值得一提的是CORS的作用。
简单的场景是您访问foo.com
并且网站执行 JavaScript 以向您发出基于 AJAX 的 DELETE 请求api.com/users/123
并最终代表您删除用户。现在这并不总是可能的,因为 CORS - 浏览器将阻止foo.com
向api.com
除非api.com
明确列入白名单的请求foo.com
。
这还假设您对 API使用基于会话的身份验证,而不是基于令牌的身份验证。在基于会话的身份验证中,任何登录的用户都api.com
可以在保持登录状态时执行请求。如果您有基于令牌的身份验证(每个请求必须使用Authorization
包含身份验证令牌的 HTTP 标头制作),那么您是安全的。基于会话的身份验证通过 cookie 隐式发送身份验证令牌。
稍微糟糕一点的情况是,如果您的一个受信任的 CORS 域遭到入侵 - 假设您有一个不清理 JavaScript 的表单,并且用户设法通过该表单将 JS 注入您的站点。如果您使用基于会话的身份验证,则访问该页面的经过身份验证的用户将看到 JavaScript 运行并发出 API 请求。如果您对 API 使用基于会话的身份验证,这可能是灾难性的并且非常有可能。
根据DRF 文档,只要服务器使用经过身份验证的会话(而不是每次都询问密码),API 就容易受到 CSRF 攻击
解决方案是
GET
)不能用于更改任何服务器端状态。HEAD
OPTIONS
POST
、和PUT
,始终需要有效的 CSRF 令牌。PATCH
DELETE