【问题标题】:401 unauthorized for PUT/PATCH/DELETE with Devise and Rails-api401 未经授权使用 Devise 和 Rails-api 进行 PUT/PATCH/DELETE
【发布时间】:2015-10-25 17:33:54
【问题描述】:

我有一个集成了 Devise 和 Doorkeeper 的 RAILS API。我对 registrations#create 的 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

搜索路线

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(覆盖设计)

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

应用程序.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

【问题讨论】:

  • skip_before_filter :verify_authenticity_token 是在controlle上禁用CSRF保护。 skip_before_filter :authenticate_user! 应该可以工作。

标签: ruby-on-rails devise routes


【解决方案1】:

您已选择性地覆盖Devise::RegistrationsController 方法,即:new, :edit, :cancel

Rest 方法未在您的类中定义,因此它们将由 Devise::RegistrationsController 提供服务。

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

class Devise::RegistrationsController < DeviseController
  prepend_before_filter :require_no_authentication, only: [:new, :create, :cancel]
  prepend_before_filter :authenticate_scope!, only: [:edit, :update, :destroy]

如您所见,:create 操作不需要身份验证,因此您看不到 POST 请求的 401,因为它与 create 操作匹配。

PUT/PATCH 匹配需要身份验证的 update 操作,类似地,DELETE 匹配也需要身份验证的“销毁”操作,因此您会收到此 401 错误。

要解决此问题,请在覆盖 RegistrationsController 中的操作后添加 doorkeeper authorize 以获取受保护的操作。

【讨论】:

  • 感谢@Anial Maurya,我必须将skip_before_filter :authentication_scope! 放入我的自定义注册控制器并添加doorkeeper_authorize: api。此外,我还必须覆盖 current_userupdate_resource 才能使完整的 CRUD 操作正常工作。
猜你喜欢
  • 1970-01-01
  • 2021-04-26
  • 2019-03-07
  • 2017-09-27
  • 2014-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多