问题 从控制器请求对象中获取Authorization标头的正确方法是什么?


我有两个RSpec测试,一个控制器规范和一个请求规范,我正在向同一个控制器的索引操作发出GET请求。在这两个规范中,我发送的Authorization标头包含一个Oauth2承载令牌。

我遇到的问题是,根据规范的类型,标头存储在请求对象的不同属性上。在请求规范的情况下,可以在 request.env["Authorization"] 在控制器规格的情况下,它可以在 request.session["Authorization"]

为什么“授权”存储在不同类型的规格的不同位置?有什么地方我可以找到两个规格吗?

这个 bearer_token 方法是在父控制器类中,我从标头中抓取令牌:

适用 env 在请求规范中:

def bearer_token
  pattern = /^Bearer /
  header  = request.env["Authorization"] # <= env
  header.gsub(pattern, '') if header && header.match(pattern)
end

适用 session 在控制器规格中:

def bearer_token
  pattern = /^Bearer /
  header  = request.session["Authorization"] # <= session
  header.gsub(pattern, '') if header && header.match(pattern)
end

这是我的要求规范:

describe '' do
  let(:user) { Fabricate(:user) }

  describe 'accessing content with valid token' do
    let(:token) { OauthToken.create(user: user) }
    let(:auth_headers) { {
      'Authorization' => "Bearer #{token.access_token}",
      'HTTPS' => 'on'
    } }
    before { get api_v2_cats_path, {}, auth_headers }
    specify { response.status.should == 200 }
  end
end

这是我的控制器规格

describe Api::V2::CatsController do
  let(:user) { Fabricate(:user) }

  describe ".index" do
    let(:token) { OauthToken.create(user: user) }
    let(:auth_headers) { {
      'Authorization' => "Bearer #{token.access_token}",
      'HTTPS' => 'on'
    } }

    it "should be valid" do
      get :index, { format: :json, page_size: 1 }, auth_headers
      @json = JSON.parse(response.body)
      @json.should_not be_nil
    end
  end
end

10324
2017-08-08 14:41


起源



答案:


我认为API将是相同的 get 请求和控制器规范之间的方法。在控制器规范中,第三个参数是会话变量的散列,而不是标头变量。您可以直接在标题上设置标题 @request 像这样的对象:

describe Api::V2::CatsController do
  let(:user) { Fabricate(:user) }

  describe ".index" do
    let(:token) { OauthToken.create(user: user) }
    let(:auth_headers) { {
      'Authorization' => "Bearer #{token.access_token}",
      'HTTPS' => 'on'
    } }

    before do
      @request.env.merge!(auth_headers)
    end

    it "should be valid" do
      get :index, { format: :json, page_size: 1 }
      @json = JSON.parse(response.body)
      @json.should_not be_nil
    end
  end
end

然后获取授权标头的正确方法是使用:

def bearer_token
  pattern = /^Bearer /
  header  = request.env["Authorization"] # <= env
  header.gsub(pattern, '') if header && header.match(pattern)
end

10
2017-08-08 14:56



只是一个改进,你可以来自 header.gsub(pattern, '') if header && header.match(pattern) 至 header.gsub(pattern, '') if header&.match(pattern) - Mateus Luiz


答案:


我认为API将是相同的 get 请求和控制器规范之间的方法。在控制器规范中,第三个参数是会话变量的散列,而不是标头变量。您可以直接在标题上设置标题 @request 像这样的对象:

describe Api::V2::CatsController do
  let(:user) { Fabricate(:user) }

  describe ".index" do
    let(:token) { OauthToken.create(user: user) }
    let(:auth_headers) { {
      'Authorization' => "Bearer #{token.access_token}",
      'HTTPS' => 'on'
    } }

    before do
      @request.env.merge!(auth_headers)
    end

    it "should be valid" do
      get :index, { format: :json, page_size: 1 }
      @json = JSON.parse(response.body)
      @json.should_not be_nil
    end
  end
end

然后获取授权标头的正确方法是使用:

def bearer_token
  pattern = /^Bearer /
  header  = request.env["Authorization"] # <= env
  header.gsub(pattern, '') if header && header.match(pattern)
end

10
2017-08-08 14:56



只是一个改进,你可以来自 header.gsub(pattern, '') if header && header.match(pattern) 至 header.gsub(pattern, '') if header&.match(pattern) - Mateus Luiz