ruby-on-rails - 使用 key HTTP_AUTHORIZATION 而不是授权访问 Ruby on Rails 中的授权 header ?

标签 ruby-on-rails http

我希望有人能为我解决一些问题。我正在使用 Rails 2.3.5,我可以像这样在 Controller 操作中访问请求 header :

def index
  if request.headers['...'] == '...'
    ...
  end
end

或类似的东西。 request.headers 是 ActionController::Http::Headers 的一个实例这似乎是一个哈希。因此,我希望 header 以我发送的名称为关键字。但是,如果我发送请求,带有 Authorization header ,像这样:

curl -H 'Authorization: OAuth realm="MyRealm",...' http://app/path

操作中的以下代码返回 false:

if request.headers.include?('Authorization') ... 

而以下回应了我在 header 中发送的值:

render :text => request.headers['Authorization']

有趣的是,以下检查返回 true:

if request.headers.include?('HTTP_AUTHORIZATION') ... 

类似地,以下回应了我在 header 中发送的值:

render :text => request.headers['HTTP_AUTHORIZATION']

似乎发生了一些我不知道的魔法。我完全不明白为什么检查 key “授权”失败,但呈现 request.headers['Authorization'] 的值却成功。我也对“HTTP_AUTHORIZATION”的来源感到困惑,因为它不是我随请求发送的 header 的名称。任何人都知道到底发生了什么?

最佳答案

你是对的 - ActionController::Requestheaders 方法返回一个 ActionController::Http::Headers 的实例,它是继承自哈希。如果我们破解源代码,我们会看到:

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

因此,当通过 [] 访问哈希时,会进行第二次检查以查看是否来自 env_name 的值(它只是将键大写并添加 HTTP_) 存在。

这就是为什么您无法从 request.headers.include?('Authorization') 中获取真实值的原因 -- include? 未在子类中被覆盖检查 header 的正常版本和大写版本。我想您可以效仿并像这样自己实现它:

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 中要求它,您应该可以开始了。不过,我建议只修改您的 Controller 代码以使用 []present? 进行检查:)

原因,标题被大写并以 HTTP_ 为前缀,我相信,源于 Rails 的 HTTP 中间件 Rack。它可能这样做是为了保持对大小写的公正,另外在 HTTP_ 之前加上以避免与进来的其他非 header 环境内容发生冲突。

所以,是的,有点神奇,但在浏览了源代码后并不难理解,我一直推荐 :) Rails 有一些非常好的源代码,我多年来从中学到了很多东西。

关于ruby-on-rails - 使用 key HTTP_AUTHORIZATION 而不是授权访问 Ruby on Rails 中的授权 header ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2311883/

相关文章:

xml - 使用http在golang中读取FederationMetadata.xml

angularjs - angulars $resource 是否支持 etags?

http - 获取 505 HTTP 版本在 HTTPS 上不受支持,但在 HTTP 上不受支持

c# - 在 C# 中开发 HTTP 监视器

java - UrlConnection.getHeaderField(字符串名称) 返回 null

ruby-on-rails - SSL_connect returned=1 errno=0 state=SSLv3 读取服务器证书 B : certificate verify failed

ruby-on-rails - 从字符串或字符串数​​组中删除多余的垃圾词

javascript - ruby 哈希到 javascript 哈希

ruby-on-rails - Rails 3 - 如何...在数据库列字段数据中存储非结构化数据

javascript - rails/javascript : "too many parameter keys" - what's a good way to normalize form data?