protect_from_forgery和skip_forger
跨站点请求伪造(CSRF)
rails 包含一个用于防止CSRF
的内置机制,在生成应用程序时,protect_from_forgery
默认包含在application_controller.rb
控制器。
rails利用绑定到用户会话的同步器令牌(加密随机令牌)。
form表单创建时,会创建一个name
为authenticity_token
的隐藏input
字段,该字段包含同步器令牌,随表单提交时一起发送。在处理发送的post(仅验证通过post请求发送的)请求时,参数提交的值与用户关联的值进行比较,不匹配则有可能是攻击者伪造的恶意请求。
我们调用protect_from_forgery
方法,我们实际上是在创建一个调用该verify_authenticity_token
函数的before
过滤器。
verify_authenticity_token
函数运行时,他会检查是否已通过调用vertified_request?
方法验证了请求。验证失败后他会发出警告,并调用该handle_unverfied_request
方法。
handle_unverified_request
反过来调用ActionDispatch_reset_session
帮助程序来破坏与伪造请求相关联的会话。
rails4中,protect_from_forgery
方法在从伪造请求中清除敏感信息时会占用cookie。
handle_unverified_request
方法也重新调整为调用ProtectionMethods
模块中的handle_unverified_request
帮助程序。
def protect_from_forgery(option={})
self.request_forgery_protection_token || = :authenticity_token
prepend_before_filter :verify_authenticity_token, options
end
def verfity_authenticity_token
unless verify_request?
logger.warn "WARNING: Can't verify CSRF token authenticity" if logger
handle_unverified_request
end
end
protect_from_forgery(options = {})
请求打开伪造保护。不检查GET和HEAD请求。
class ApplicationController < ActionController::Base
protect_from_forgery
end
class FooController < ApplicationController
protect_from_fogery except: :index
end
你可以通过跳过验证before_action
来禁用控制器上的伪造保护。
- :only/:except 仅对部分操作应用伪造保护
- :if/:unless 根据通过的proc或方法参考,完全关闭伪造保护。
- :prepend 默认情况下,身份验证令牌的验证将添加到应用程序中 protect_from_forgery 调用的位置。这意味着先运行之前添加的任何回调。当您希望伪造保护依赖于其他回调时,这非常有用。
如果你希望将验证添加到回调链的开头,使用prepend: true
- :with 设置方法以处理未验证的请求
有效的未经验证的请求处理方法是:
- :except引发ActionController::InvalidAuthenticityToken异常
- :reset_session 重置回话
- :null_session 在请求期间提供空会话,但不会完全重置,如果:with未指定选项,则用作默认值
skip_forgery_protection(options = {})
关闭请求伪造保护
skip_before_action :verify_authenticity_token