【问题标题】:Rails api gem and devise token authenticationRails api gem 和设计令牌认证
【发布时间】:2013-05-29 20:33:45
【问题描述】:

如果有人可以提供一些启示,我将不胜感激,因为我对这个问题有点无能为力。基本上,我正在尝试使用构建在rails-api gem 之上的仅 JSON rails rest api 应用程序来完成设计身份验证。

我已经实现了SessionsRegistrations 处理,如下所述。

class ApplicationController < ActionController::API
    include ActionController::MimeResponds
end

sessions_controller.rb

  class SessionsController < Devise::SessionsController
    prepend_before_filter :require_no_authentication, :only => [:create ]

    before_filter :ensure_params_exist
    def create
      build_resource
      resource = User.find_for_database_authentication(:email => params[:user][:email])
      return invalid_login_attempt unless resource

      if resource.valid_password?(params[:user][:password])
        sign_in("user", resource)
        render :json=> {:success=>true, :auth_token=>resource.authentication_token, :email=>resource.email}
      return
      end
      invalid_login_attempt
    end

    def destroy
      sign_out(resource_name)
    end

    protected

    def ensure_params_exist
      return unless params[:user][:email].blank?
      render :json=>{:success=>false, :message=>"missing login email parameter"}, :status=>422
    end

    def invalid_login_attempt
      warden.custom_failure!
      render :json=> {:success=>false, :message=>"Error with your login or password"}, :status=>401
    end

  end

registrations_controller.rb

  class RegistrationsController < Devise::RegistrationsController
    skip_before_filter :verify_authenticity_token, :only => :create

    def create
      user = User.new(params[:user])
      if user.save
        render :json=> {:user => [:email => user.email, :auth_token => user.authentication_token]}, :status => 201
      return
      else
        warden.custom_failure!
        render :json=> user.errors, :status=>422
      end
    end
  end

到目前为止一切正常。在我的其他控制器中,我添加了这条线来保护它们。 before_filter :authenticate_user! 但使用 auth_token 调用时出现此错误。 ?auth_token=xxxxxxxxxxx

undefined method authenticate_user!

控制器
class RestaurantsController < ApplicationController

        before_filter :authenticate_user!

      def index
        @restaurants =  Restaurant.all

      end

      def show
        @restaurant = Restaurant.find(params[:id])

      end
    end

仍然不确定这里可能是什么问题 - 我假设这是因为使用 ActionController::API 时缺少正确设计的东西

更新 看来问题出在我的routes.rb 本身 - 这就是路线的完成方式。

require 'api_constraints'

MyApi::Application.routes.draw do

  namespace :api, defaults: {format: 'json'} do
    scope module: :v1, constraints: ApiConstraints.new(version: 1,default: true) do
      devise_for :users
      resources :friends
      resources :locations
      resources :profiles
      resources :users


    end

    scope module: :v2, constraints: ApiConstraints.new(version: 2) do
    # Future releases of the API can go here
    end

  end

end

现在如果在范围之外重复devise_for :users,一切都开始工作了。

require 'api_constraints'

MyApi::Application.routes.draw do

  namespace :api, defaults: {format: 'json'} do
    scope module: :v1, constraints: ApiConstraints.new(version: 1,default: true) do
      devise_for :users
      resources :friends
      resources :locations
      resources :profiles
      resources :users


    end

    scope module: :v2, constraints: ApiConstraints.new(version: 2) do
    # Future releases of the API can go here
    end

  end
devise_for :users
end

有人解释为什么吗?

【问题讨论】:

  • 问题已更新 - 添加路线。
  • 您的问题如此太好了,我用它来修复我自己的代码。我希望你现在已经找到了解决方案:)

标签: ruby-on-rails devise rails-api


【解决方案1】:

步骤 1. 使用自定义控制器覆盖设计控制器,将重定向替换为 JSON 响应。 Here's a custom SessionController that uses JSON responses.

第 2 步。如果发生身份验证错误,控制权会转到使用 failure_app 的守望者,它只是一个 Rack 应用程序,它设置闪存消息并根据请求的格式呈现/重定向。您需要一个自定义 json 响应,其中包含一个包含错误数组的错误键,而不是默认的错误键。所以你需要一个 custom_auth_failure_app.rb 在 config/initializers 下,this content

第 4 步。现在我们必须通过将其添加到 config/initializers/devise.rb 来告诉 Devise 使用自定义故障应用程序:

config.warden do |manager|
  manager.failure_app = CustomAuthFailure
end

步骤 5. 在设计模型中启用 token_authenticatable 并将以下内容添加到 config/initializers/devise.rb

config.http_authenticatable = true
config.skip_session_storage = [:http_auth, :token_auth]

第 6 步。如果您使用的是不使用会话的真正 JSON API,请使用具有处理零会话的补丁的 Warden (> 1.2.2) 版本。

另请阅读我的blog post about creating a tested, documented and versioned JSON API using Rails4 + Rails-API + Devise,其中谈到了所有这些步骤。

【讨论】:

  • 感谢 emil,但问题 authenticate_user 助手不起作用。设置与您的相同。
  • 看看这个sample app on github。这应该会有所帮助
  • 谢谢 Emil :) 会看看
  • 第 3 步发生了什么? O.o
【解决方案2】:

对于遇到同样问题的任何人,在使用 devise_token_authrails-api 时,设计辅助方法(如 authenticate_user)不起作用,请尝试将此行添加到 app/controllers/application_controller.rb:

include DeviseTokenAuth::Concerns::SetUserByToken

当您运行devise_token_auth 安装时,it is supposed to automatically create this concern 在 ApplicationController 中。这个关注gives access to the helper methods 就像authenticate_user。问题是,that concern doesn't get added 如果您使用的是rails-api 而不是香草导轨。所以,你必须手动添加它。

不确定根本原因,但我怀疑是因为 rails-api 的 ApplicationController 继承自 ActionController::API,这与 vanilla rails 的 ApplicationController 不同,后者继承自 ActionController::Base。

【讨论】:

    猜你喜欢
    • 2017-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多