Rails api gem和设计令牌认证

时间:2013-06-03 16:02:02

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

如果有人可以解决一些问题,我会非常感激,因为我对这个问题毫无头绪。基本上我正在尝试使用仅构建在rails-api gem之上的JSON only rails rest api app来完成设计认证。

我已经实施了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

有人解释原因吗?

3 个答案:

答案 0 :(得分:6)

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

步骤2.如果发生身份验证错误,控件将进入warden,该warden使用的failure_app只是一个Rack应用程序,它根据请求的格式设置Flash消息并呈现/重定向。您需要一个自定义的json响应,其中包含一个错误键,而不是默认的错误键。因此,您需要在{/ 3}}的config / initializers下使用custom_auth_failure_app.rb。

步骤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)版本,该版本具有处理nil会话的补丁。

另请阅读我的this content,其中讨论了所有这些步骤。

答案 1 :(得分:1)

对于遇到同样问题的人,使用authenticate_userdevise_token_auth时,rails-api等设计助手方法无效,请尝试将此行添加到app / controllers / application_controller.rb:

include DeviseTokenAuth::Concerns::SetUserByToken

在ApplicationController中运行devise_token_auth安装时,it is supposed to automatically create this concern。这个问题gives access to the helper methods就像authenticate_user一样。如果你使用rails-api代替vanilla rails,问题是that concern doesn't get added。所以,你必须手动添加它。

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

答案 2 :(得分:-4)

看起来你的Devise模型并没有被命名为User。 Devise生成身份验证_#{model_name}!基于设计用户/人/管理员/等模型的功能。