Rails API设计,不会禁用CSRF保护

Ste*_*sen 44 api ruby-on-rails csrf

早在2011年2月,Rails 就更改为要求所有非GET请求的CSRF令牌,甚至是API端点的请求.我理解为什么这是浏览器请求的重要更改的解释,但该博客文章没有提供有关API应如何处理更改的任何建议.

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

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

似乎令牌不会从一个POST更改为另一个POST.假设令牌在会话期间不会改变是否安全?

我不喜欢会话到期时的额外错误处理,但我认为它比在每个POST/PUT/DELETE请求之前获取令牌更好.

Chr*_*ola 48

老问题,但安全性很重要,我觉得它应该得到一个完整的答案.正如在这个问题中讨论的那样,即使使用API​​,CSRF仍然存在一些风险.是的浏览器默认情况下应该防范这种情况,但由于您没有完全控制用户安装的浏览器和插件,因此仍应将其视为防止API中的CSRF的最佳做法.

我有时看到它的方式是从HTML页面本身解析CSRF元标记.我并不喜欢这个,因为它不适合今天许多单页+ API应用程序的工作方式,我觉得应该在每个请求中发送CSRF令牌,无论它是HTML,JSON还是XML.

所以我建议通过后过滤器为所有请求传递CSRF令牌作为cookie或标头值.API可以简单地将其重新提交为X-CSRF-TokenRails已经检查的标头值.

这就是我使用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
Run Code Online (Sandbox Code Playgroud)

AngularJS会自动查找名为cookie的cookie,XSRF-TOKEN但随时可以为您的目的命名.然后,当您提交POST/PUT/DELETE时,您应该设置X-CSRF-TokenRails自动查找的标头属性.

不幸的是,AngualrJS已经XSRF-TOKEN在标头值中发送回cookie X-XSRF-TOKEN.很容易覆盖Rails的默认行为以适应这种ApplicationController情况:

  protected

  def verified_request?
    super || form_authenticity_token == request.headers['X-XSRF-TOKEN']
  end
Run Code Online (Sandbox Code Playgroud)

对于Rails 4.2,现在有一个内置的帮助程序,用于验证应该使用的CSRF.

  protected

  def verified_request?
    super || valid_authenticity_token?(session, request.headers['X-XSRF-TOKEN'])
  end
Run Code Online (Sandbox Code Playgroud)

我希望这很有帮助.

编辑:在我对提交的Rails pull-request讨论中发现,将CSRF令牌传递给API进行登录是一种特别糟糕的做法(例如,有人可以为您的站点创建使用用户凭据的第三方登录而不是代币).如此幽默的经纪人.由您来决定您对应用程序的关注程度.在这种情况下,您仍然可以使用上述方法,但只将CSRF cookie发送回已经具有经过身份验证的会话而不是每个请求的浏览器.这将阻止在不使用CSRF元标记的情况下提交有效登录.

  • 您的编辑至关重要:服务器应仅为经过身份验证的用户设置CSRF cookie. (3认同)

Ari*_*jan 6

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

当然,您应该通过要求HTTP身份验证或自定义实现的API令牌或OAuth解决方案保护您的API.

  • "这与API无关,因为它们不能在浏览器中运行":有时浏览器*是API的客户端 - 也就是说, (11认同)
  • 我链接的页面不同意:"浏览器插件和HTTP重定向的某些组合可用于欺骗用户的浏览器发出跨域请求,其中包括攻击者指定的任意HTTP头.攻击者可以利用它来欺骗ajax和API请求并绕过内置的CSRF保护并成功攻击应用程序." (2认同)