Rails CSRF保护+Angular.js:Protect_For_forary使我在POST上登出

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (30)

如果protect_from_forgery在应用程序中提到了选项。_控制器,然后我可以登录并执行任何GET请求,但是在第一次POST请求Rails上会重置会话,这会使我退出。

protect_from_forgery选项暂时关闭,但希望将其与Angular.js一起使用。有什么办法吗?

提问于
用户回答回答于

我认为从DOM中读取CSRF值不是一个好的解决方案,它只是一个解决办法。

因为只有运行在域上的JavaScript才能读取cookie,所以可以确保服务器的XHR来自运行在域上的JavaScript。 为了利用这一点(CSRF保护),服务器需要在第一个HTTPGET请求上设置一个名为XSRF的JavaScript可读会话cookie中的令牌。在随后的非GET请求中,服务器可以验证cookie是否与X-XSRF-令牌HTTP报头匹配。

以下是基于这些说明的解决方案:

首先,设置cookie:

# app/controllers/application_controller.rb

# Turn on request forgery protection
protect_from_forgery

after_action :set_csrf_cookie

def set_csrf_cookie
  cookies['XSRF-TOKEN'] = form_authenticity_token if protect_against_forgery?
end

然后,我们应该在每个非GET请求上验证令牌。

既然Rails已经用类似的方法构建了,我们就可以简单地重写它来附加我们的逻辑:

# app/controllers/application_controller.rb

protected

  # In Rails 4.2 and above
  def verified_request?
    super || valid_authenticity_token?(session, request.headers['X-XSRF-TOKEN'])
  end

  # In Rails 4.1 and below
  def verified_request?
    super || form_authenticity_token == request.headers['X-XSRF-TOKEN']
  end
用户回答回答于

使用的是默认的Rails CSRF保护(<%= csrf_meta_tags %>),可以像这样配置角度模块:

myAngularApp.config ["$httpProvider", ($httpProvider) ->
  $httpProvider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content')
]

或者,如果不使用CoffeeScript:

myAngularApp.config([
  "$httpProvider", function($httpProvider) {
    $httpProvider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content');
  }
]);

可以只在非GET请求时发送标头,如下所示:

myAngularApp.config ["$httpProvider", ($httpProvider) ->
  csrfToken = $('meta[name=csrf-token]').attr('content')
  $httpProvider.defaults.headers.post['X-CSRF-Token'] = csrfToken
  $httpProvider.defaults.headers.put['X-CSRF-Token'] = csrfToken
  $httpProvider.defaults.headers.patch['X-CSRF-Token'] = csrfToken
  $httpProvider.defaults.headers.delete['X-CSRF-Token'] = csrfToken
]

扫码关注云+社区