在服务Web和API的Rails应用程序中正确使用protect_from_forgery

Rom*_*149 6 csrf-protection ruby-on-rails-4

我正在开发一个通过API为移动应用程序提供服务的Rails 4应用程序,并且有一个用于管理员管理应用程序的Web UI.还有一些用户可以看到的网页(成功的电子邮件确认和重置密码).

我创建了两组控制器:一组继承自APIController,另一组继承自AdminController.这两个都继承自ApplicationController.负责面向用户的网页的其余控制器也继承自ApplicationController.

鉴于此方案,我不确定如何使用protect_from_forgery正确实施CSRF保护.我目前有以下内容:

class ApplicationController < ActionController::Base
  # ...
end

module API
  class APIController < ApplicationController
    protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format == 'application/json' }
    # ...
  end
end

module Admin
  class AdminController < ApplicationController
    protect_from_forgery with: :exception
    # ...
  end
end

class UsersController < ApplicationController
  protect_from_forgery with: :exception
  # ...
end
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:这是正确的吗?有没有办法改善它?APIController中的检查是否毫无意义,因为所有API请求都只是JSON吗?

Brakeman抱怨说ApplicationController中没有protect_from_forgery调用,但也许它看不到子类中的调用.

提前致谢!

cas*_*ral 3

您可以在他们的(brakeman)Github 页面上ApplicationController看到,它检查唯一的存在

您的管理员和用户控制器可以使用protect_from_forgery with: :exception

Rails 4 上的默认行为protect_from_forgery:null_session,您可以with:根据需要删除该选项。

关于改进,我将实现一种在用户中保存令牌并匹配每个请求的方法,这样请求 API 的用户必须在每个请求中发送他的令牌。这样做可以避免获取 CSRF 令牌然后使用此令牌发送请求的必要性。例如,对于移动用户来说,这是一项额外的请求,您只需保存正确的令牌即可解决。如果有人获得此令牌,它可以作为用户传递并更改数据。但您可以寻找更多方法来提高安全性。

如果您将令牌保存在会话或 cookie 中,则可能会发生 CSRF,如果您选择这样保存,则必须独立处理该问题。

如果你打算在手机上使用API​​,请将令牌(在我首先说的策略中)保存在手机(内存或本地数据库)上,这样会更安全。