当 CSRF token 不匹配时,Rails 会引发一个 InvalidAuthenticityToken
。但是,通过阅读 source ,我无法弄清楚这实际上是如何发生的。我首先确认该类的树:
$ ack --ignore-dir=test InvalidAuthenticityToken
actionpack/lib/action_controller/metal/request_forgery_protection.rb
4: class InvalidAuthenticityToken < ActionControllerError #:nodoc:
17: # which will check the token and raise an ActionController::InvalidAuthenticityToken
actionpack/lib/action_dispatch/middleware/show_exceptions.rb
22: 'ActionController::InvalidAuthenticityToken' => :unprocessable_entity
只有两次点击,忽略评论。第一个是类定义:
class InvalidAuthenticityToken < ActionControllerError #:nodoc:
end
第二个是将异常转换为 HTTP 状态代码。通过在 Controller 中调用 protect_from_forgery
启用 CSRF 保护,让我们看一下:
def protect_from_forgery(options = {})
self.request_forgery_protection_token ||= :authenticity_token
before_filter :verify_authenticity_token, options
end
它添加了一个过滤器:
def verify_authenticity_token
verified_request? || handle_unverified_request
end
验证失败时调用:
def handle_unverified_request
reset_session
end
那么 InvalidAuthenticityToken
是如何产生的呢?
最佳答案
行为是 changed fairly recently但文档尚未更新。正在使用的新方法是假定 session 已被劫持,因此清除 session 。假设您的 session 包含此请求的所有重要身份验证信息(例如您以 alice
身份登录的事实)并且您的 Controller 确保用户已通过此操作的身份验证,您的请求将被重定向到登录页面(或者您选择处理未登录的用户)。但是,对于未经过身份验证的请求(如注册表单),请求将使用空 session 进行。
似乎这个提交也继续关闭一个 CSRF vulnerability ,但我没有仔细阅读其中的细节。
要获得旧的行为,您只需定义此方法:
def handle_unverified_request
raise(ActionController::InvalidAuthenticityToken)
end
您可以在 Ruby on Rails Security Guide 阅读更多关于 CSRF 和其他 Rails 安全问题的信息.
关于ruby-on-rails - Rails CSRF 保护是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5000333/