使用密钥HTTP_AUTHORIZATION而不是Authorization访问Ruby on Rails中的授权标头?
我希望有人可以为我清理一些东西。 我正在使用Rails 2.3.5,我可以在控制器动作中访问请求标头,如下所示:
def index if request.headers['...'] == '...' ... end end
或类似的东西。 request.headers是ActionController :: Http :: Headers的一个实例,它看起来像是一个Hash。 因此,我希望标题键在我发送的名称上。 但是,如果我发送请求,请使用Authorization标头,如下所示:
curl -H 'Authorization: OAuth realm="MyRealm",...' http://app/path
操作中的以下代码返回false:
if request.headers.include?('Authorization') ...
以下回应我在标题中发送的值:
render :text => request.headers['Authorization']
以下检查返回true,有趣的是:
if request.headers.include?('HTTP_AUTHORIZATION') ...
同样,以下内容回显了我在标题中发送的值:
render :text => request.headers['HTTP_AUTHORIZATION']
似乎有一些我不知道的神奇事件。 我完全混淆为什么检查密钥’授权’失败,但渲染request.headers [‘Authorization’]的值成功。 我也很困惑’HTTP_AUTHORIZATION’来自何处,因为这不是我随请求发送的标头的名称。 有谁知道究竟发生了什么?
你是对的 – ActionController::Request
的headers
方法返回一个ActionController::Http::Headers
的实例,它inheritance自Hash。 如果我们破解源代码,我们会看到:
class Headers < ::Hash extend ActiveSupport::Memoizable def initialize(*args) if args.size == 1 && args[0].is_a?(Hash) super() update(args[0]) else super end end def [](header_name) if include?(header_name) super else super(env_name(header_name)) end end private # Converts a HTTP header name to an environment variable name. def env_name(header_name) "HTTP_#{header_name.upcase.gsub(/-/, '_')}" end memoize :env_name end
因此,当通过[]
访问Hash时,会进行第二次检查,以查看是否存在来自env_name
值(它只是提升了密钥并预先设置了HTTP_
)。
这就是为什么你无法从request.headers.include?('Authorization')
获得真正的价值request.headers.include?('Authorization')
- include?
未在子类中重写以检查标头的正常版本和更新版本。 我想你可以效仿并自己实现这样:
module ActionController module Http class Headers < ::Hash def include?(header_name) self[header_name].present? end end end end
把它扔进lib/extensions/action_controller.rb
东西,必要时在environment.rb
需要它,你应该好好去。 我建议只修改你的控制器代码以使用[]
并present?
做检查,但:)
我相信,标题是upxased并以HTTP_
为前缀的原因源于Rack,Rails的HTTP中间件。 这可能是为了保持对案件的公正,另外在HTTP_
之前预先设置,以避免与其他非标题环境内容冲突。
所以,是的,有点神奇,但在浏览源代码后并不难理解,我总是建议这样做:Rails有一些非常好的来源,我多年来从中学到了很多东西。
根据通用网关接口RFC :
如果使用的协议是HTTP,则名称以
"HTTP_"
开头的元变量包含从客户端请求头字段读取的值。 HTTP标头字段名称转换为大写,所有出现的"-"
替换为"_"
并且前面有"HTTP_"
以提供元变量名称。