Rails APIdevise不禁用CSRF保护

早在2011年2月,Rails就被更改为要求所有非GET请求的CSRF令牌 ,即使是针对API端点的CSR请求也是如此。 我理解为什么这是浏览器请求的一个重要变化的解释,但是博客文章没有提供关于API如何处理变化的任何build议。

我对禁用某些操作的CSRF保护不感兴趣。

API应该如何处理这个变化? 是否期望API客户端向API发出GET请求以获取CSRF令牌,然后在该会话期间的每个请求中包含该令牌?

看起来,令牌不会从一个POST改变到另一个。 假设令牌在会话期间不会改变是否安全?

当会话过期时,我不喜欢额外的error handling,但是我认为比在每个POST / PUT / DELETE请求之前必须获取一个令牌要好。

老问题,但安全是足够重要的,我觉得它值得一个完整的答案。 正如在这个问题中所讨论的,即使使用API​​,CSRF仍然存在一些风险。 是的,浏览器在默认情况下应该防范这种情况,但是由于您没有完全控制用户安装的浏览器和插件,因此在您的API中保护CSRF不失为一种最佳做法。

我有时看到它的做法有时是从HTML页面parsingCSRF元标记。 我不太喜欢这个,因为它不适合很多单页面API应用程序的工作方式,我觉得CSRF令牌应该在每个请求中发送,而不pipe它是HTML,JSON还是XML。

所以我build议通过一个后置filter来传递一个CSRF标记作为一个cookie或者标题值来处理所有的请求。 API可以简单地重新提交,作为Rails已经检查过的X-CSRF-Token的头部值。

这是我用AngularJS做的:

  # In my ApplicationController after_filter :set_csrf_cookie def set_csrf_cookie if protect_against_forgery? cookies['XSRF-TOKEN'] = form_authenticity_token end end 

AngularJS会自动查找一个名为XSRF-TOKEN 的cookie,但随意为您的目的命名它。 然后当你提交一个POST / PUT / DELETE时,你应该设置Rails自动寻找的头部属性X-CSRF-Token

不幸的是,AngualrJS已经在X-XSRF-TOKEN的头部值中发送了XSRF-TOKEN cookie。 覆盖Rails的默认行为很容易,以适应这样的ApplicationController这样的:

  protected def verified_request? super || form_authenticity_token == request.headers['X-XSRF-TOKEN'] end 

对于Rails 4.2,现在有一个内置的帮助器来validation应该使用的CSRF。

  protected def verified_request? super || valid_authenticity_token?(session, request.headers['X-XSRF-TOKEN']) end 

我希望这是有帮助的。

编辑:在一个关于这个Rails拉取请求的讨论中,我提出了将CSRF令牌通过API用于login是一个特别糟糕的做法(例如,某人可以为您的站点创build使用用户凭据的第三方login而不是令牌)。 所以c em不驯。 这取决于您是否对您的应用程序感到担心。 在这种情况下,您仍然可以使用上述方法,但只能将CSRF Coo​​kie发送回已经具有validation会话的浏览器,而不是针对每个请求。 这将阻止提交有效的login,而不使用CSRF元标记。

Rails使用“默认安全”约定。 跨网站或跨会话请求伪造要求用户拥有浏览器和另一个受信任的网站。 这与API无关,因为它们不在浏览器中运行,也不维护任何会话。 因此,您应该禁用API的CSRF。

当然,您应该通过要求HTTP身份validation或自定义的API令牌或OAuth解决scheme保护您的API。