升级到rails 4.1.8并且我的api破了

时间:2014-12-01 19:19:56

标签: ruby-on-rails api ruby-on-rails-4 rspec

我没有时间通过​​.6和.7以及.8深入确保我没有遗漏某些东西,但今天我决定更新我的应用程序,这主要是一个API有一些前端工作。

我将应用程序更新到rails 4.1.8并且我的规范中出现了很多错误,事实上api必须经过身份验证的任何事情都会爆炸。

我使用api的控制器有一个名为restrict_api_access的方法,可通过

完成
  def restrict_api_access
    authenticate_or_request_with_http_token do |token, options|
      @api_key = ApiKey.find_by(api_key: token)
    end unless current_user
  end

现在您可以登录应用程序并管理内容,在这种情况下,我们仍然使用您通过终端或外部应用程序访问的相同API。所以unless current_user基本上看起来像:

  def current_user
    if (@api_key)
      @current_user = User.find_by!(id: @api_key.xaaron_users_id)
    else
      super
    end
  end

Ans然后当前用户的super基本上说明了 - 你是否登录。

因此,其中一个失败的测试设置如下:

context“创建新标签”     之前(:每个)做       @tag = FactoryGirl.build(:tag,blog_id:@ blog.id)       set_auth_header(@user)     端

it "should create a tag for a post" do
  post :create, :blog_id => @blog.id, tag: {name: @tag.name, description: 'asdasddsa'}
  json = JSON.parse(response.body)
  expect(json['tag']['name']).to eql @tag.name
end

@user设置在其他位置。但我可以向您保证,用户正在被传入并被创建。

这里另一个有趣的方法是set_auth_header(@user)这个方法如下:

# Create a random api key
def create_api_key(user)
  ApiKey.create!(:xaaron_users_id => user.id, :api_key => SecureRandom.hex(16))
end

# Set authentication headers for the API use
def set_auth_header(user)
  key = create_api_key(user)
  request.env['HTTP_AUTHORIZATION'] = "Token #{key.api_key}"
end

您可以看到我们为用户创建了一个API密钥,然后我们将请求环境变量设置为具有该API密钥。

所以在4.1.8之前(我在4.1.5)这个工作正常,我的所有测试都会过得很棒。现在,通过这个特殊测试,我得到:

  1) Api::V1::TagsController Create new tag should create a tag for a post
     Failure/Error: json = JSON.parse(response.body)
     JSON::ParserError:
       757: unexpected token at 'HTTP Token: Access denied.
       '
     # ./spec/controllers/api/v1/tags_controller_spec.rb:112:in `block (3 levels) in <top (required)>'

基本上我被拒绝访问。我已将此跟踪到restrict_api_access到第authenticate_or_request_with_http_token行:HTTP Token: Access denied.,其值为:{{1}}

4.1.8中是否有一些变化会导致我的所有需要​​身份验证的api中断?

1 个答案:

答案 0 :(得分:1)

您在此处手动计算授权标头,这可能是错误的:

request.env['HTTP_AUTHORIZATION'] = "Token #{key.api_key}"

有一个ActionController方法可以帮到你:

request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Token.encode_credentials(key.api_key)

尝试改为。