401使用Devise和Rails-api对PUT / PATCH / DELETE进行未授权

时间:2015-10-25 17:33:54

标签: ruby-on-rails devise routes

我有一个RAILS API,它集成了Devise和Doorkeeper。我对注册#proc的POST请求有效但PUT / PATCH / DELETE导致“401未授权”错误。我怀疑在Devise上进行身份验证可能存在一些问题,但这就是我被困住的地方。也许我错过了如何处理current_user或skip_before_filters?我尝试了很多东西,比如添加

skip_before_filter :verify_authenticity_token
skip_before_filter :authenticate_user!

谢谢!

的routes.rb

require 'api_constraints'

Rails.application.routes.draw do

    use_doorkeeper
    devise_for :users, only: [:registrations, :passwords, :confirmations], controllers: {registrations: "api/registrations"}, defaults: { format: :json }

    namespace :api, defaults: { format: :json }, constraints: { subdomain: 'api' }, path: '/' do
        scope module: :v1, constraints: ApiConstraints.new(version: 1, default: true) do
            get 'users/me', to: 'users#me'
        end
    end
end

rake routes

Prefix Verb   URI Pattern                                  Controller#Action
                          GET    /oauth/authorize/:code(.:format)             doorkeeper/authorizations#show
      oauth_authorization GET    /oauth/authorize(.:format)                   doorkeeper/authorizations#new
                          POST   /oauth/authorize(.:format)                   doorkeeper/authorizations#create
                          DELETE /oauth/authorize(.:format)                   doorkeeper/authorizations#destroy
              oauth_token POST   /oauth/token(.:format)                       doorkeeper/tokens#create
             oauth_revoke POST   /oauth/revoke(.:format)                      doorkeeper/tokens#revoke
       oauth_applications GET    /oauth/applications(.:format)                doorkeeper/applications#index
                          POST   /oauth/applications(.:format)                doorkeeper/applications#create
    new_oauth_application GET    /oauth/applications/new(.:format)            doorkeeper/applications#new
   edit_oauth_application GET    /oauth/applications/:id/edit(.:format)       doorkeeper/applications#edit
        oauth_application GET    /oauth/applications/:id(.:format)            doorkeeper/applications#show
                          PATCH  /oauth/applications/:id(.:format)            doorkeeper/applications#update
                          PUT    /oauth/applications/:id(.:format)            doorkeeper/applications#update
                          DELETE /oauth/applications/:id(.:format)            doorkeeper/applications#destroy
oauth_authorized_applications GET    /oauth/authorized_applications(.:format)     doorkeeper/authorized_applications#index
oauth_authorized_application DELETE /oauth/authorized_applications/:id(.:format) doorkeeper/authorized_applications#destroy
         oauth_token_info GET    /oauth/token/info(.:format)                  doorkeeper/token_info#show
            user_password POST   /users/password(.:format)                    devise/passwords#create {:format=>:json}
        new_user_password GET    /users/password/new(.:format)                devise/passwords#new {:format=>:json}
       edit_user_password GET    /users/password/edit(.:format)               devise/passwords#edit {:format=>:json}
                          PATCH  /users/password(.:format)                    devise/passwords#update {:format=>:json}
                          PUT    /users/password(.:format)                    devise/passwords#update {:format=>:json}
 cancel_user_registration GET    /users/cancel(.:format)                      api/registrations#cancel {:format=>:json}
        user_registration POST   /users(.:format)                             api/registrations#create {:format=>:json}
    new_user_registration GET    /users/sign_up(.:format)                     api/registrations#new {:format=>:json}
   edit_user_registration GET    /users/edit(.:format)                        api/registrations#edit {:format=>:json}
                          PATCH  /users(.:format)                             api/registrations#update {:format=>:json}
                          PUT    /users(.:format)                             api/registrations#update {:format=>:json}
                          DELETE /users(.:format)                             api/registrations#destroy {:format=>:json}
        user_confirmation POST   /users/confirmation(.:format)                devise/confirmations#create {:format=>:json}
    new_user_confirmation GET    /users/confirmation/new(.:format)            devise/confirmations#new {:format=>:json}
                          GET    /users/confirmation(.:format)                devise/confirmations#show {:format=>:json}
             api_users_me GET    /users/me(.:format)                          api/v1/users#me {:format=>:json, :subdomain=>"api

registrations_controller.rb(覆盖Devise)

include ActionController::ImplicitRender

class Api::RegistrationsController < Devise::RegistrationsController
  clear_respond_to
  respond_to :json
  respond_to :html, only: []
  respond_to :xml, only: []

  skip_before_filter :verify_authenticity_token
  before_filter :not_allowed, only: [:new, :edit, :cancel]

  def not_allowed
    render json: {error: "Method Not Allowed"}, status: 405
  end

  private

  def sign_up_params
    params.require(:user).permit([
      :email,
      :password,
      :password_confirmation,
      :first_name,
      :last_name,
    ])
  end

  def account_update_params
    params.require(:user).permit([
      :email,
      :first_name,
      :last_name,
      :password,
      :password_confirmation,
      :current_password
    ])
  end
end

application.rb中

class ApplicationController < ActionController::API
  respond_to :json

  before_filter :cors_preflight_check
  after_filter :cors_set_access_control_headers

  def cors_preflight_check
    if request.method == 'OPTIONS'
      headers['Access-Control-Allow-Origin'] = '*'
      headers['Access-Control-Allow-Methods'] = 'POST, GET, PUT, DELETE, OPTIONS'
      headers['Access-Control-Allow-Headers'] = 'X-Requested-With, X-Prototype-Version, Token'
      headers['Access-Control-Max-Age'] = '1728000'

      render text: '', content_type: 'text/plain'
    end
  end

  def cors_set_access_control_headers
    headers['Access-Control-Allow-Origin'] = '*'
    headers['Access-Control-Allow-Methods'] = 'POST, GET, PUT, DELETE, OPTIONS'
    headers['Access-Control-Allow-Headers'] = 'Origin, Content-Type, Accept, Authorization, Token'
    headers['Access-Control-Max-Age'] = "1728000"
  end

  def current_resource_owner
    User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token
  end

end

1 个答案:

答案 0 :(得分:1)

您有选择地覆盖Devise::RegistrationsController的{​​{1}}方法。

您的课程中未定义休息方法,因此:new, :edit, :cancel将为其提供服务。

如果你打开设计source code,你会看到:

Devise::RegistrationsController

正如您所看到class Devise::RegistrationsController < DeviseController prepend_before_filter :require_no_authentication, only: [:new, :create, :cancel] prepend_before_filter :authenticate_scope!, only: [:edit, :update, :destroy] 操作不需要身份验证,因此:create请求不会看到401,因为它与POST操作匹配。

create与要求身份验证的PUT/PATCH操作匹配,类似update匹配'destroy'操作,这也需要身份验证,因此您收到此401错误。

要解决此问题,请在覆盖DELETE中的操作后为受保护的操作添加doorkeeper authorize