首页 > 解决方案 > devise_token_auth 总是返回 401 Unauthorized

问题描述

我正在开发一个带有 Rails API 的 Angular 应用程序。我正在使用Devise Token Authangular-token 的 6.x 分支。我可以毫无问题地 CRUD 用户,并且可以登录,但是当我尝试访问受限制的资源(通过before_action :authenticate_user!帮助程序限制的资源)时,无论我是否登录,我都会收到错误消息。

相关控制器

class QuestionsController < ApplicationController
    before_action :authenticate_user!

    # GET /questions.json
    def index
      @questions = Question.all

      # This code is never reached due to the :authenticate_user! helper, 
      # but when I comment it out, I get the following:
      puts user_signed_in?  # => false
      puts current_user     # => nil

      render json: @questions
    end

一些东西:

任何帮助将不胜感激。

来自登录的示例响应

{
    "data": {
        "id": 1,
        "email": "me@example.com",
        "provider": "email",
        "uid": "me@example.com",
        "allow_password_change": false,
        "name": null,
        "nickname": null,
        "image": null
    }
}

角码

this.authService.loginUser({
  login: '',
  password: ''
})
.subscribe(resp => {
    if (resp.status === 200) {
      this.router.navigate(['/']);
    }
  },
  err => {
    // cut for brevity
});

编辑

我发现问题在于angular-token未设置身份验证标头,因为我认为这是以下代码中的错误:

// Add the headers if the request is going to the configured server
if (this.tokenService.currentAuthData && req.url.match(this.tokenService.apiPath)) {
  (<any>Object).assign(baseHeaders, {
    'access-token': this.tokenService.currentAuthData.accessToken,
    'client':       this.tokenService.currentAuthData.client,
    'expiry':       this.tokenService.currentAuthData.expiry,
    'token-type':   this.tokenService.currentAuthData.tokenType,
    'uid':          this.tokenService.currentAuthData.uid
  });
}

由于我没有apiPath定义,因此req.url.match(this.tokenService.apiPath))被评估为false,因此永远不会添加标题。

标签: ruby-on-railsangularruby-on-rails-5rails-apidevise-token-auth

解决方案


我不知道 angular-token,但我的基于 React/Redux 的应用程序也遇到了同样的问题 - 事实证明,这确实只是标题丢失或未正确设置的问题。

出于某种原因,基于控制器似乎DeviseTokenAuth::只能通过设置client和工作access-token,但对于所有其他受保护的资源DeviseTokenAuth::Concerns::SetUserByToken,您必须完全按照预期设置all标头,并由 devise_token_auth 记录。

  • 检查标题值和格式。
  • 检查标头是否完全等于最后一个请求(在您的情况下为身份验证请求)返回的标头。
  • 另外,检查您的映射

config/initializers/devise_token_auth.rb

config.headers_names = {:'access-token' => 'access-token',
                     :'client' => 'client',
                     :'expiry' => 'expiry',
                     :'uid' => 'id',
                     :'token-type' => 'token-type' }

(它定义了预期的 http 标头的名称(不是模型/活动记录属性))。


推荐阅读