设计令牌身份验证不会为PUT路由进行身份验证

时间:2017-07-12 20:08:24

标签: ruby-on-rails ruby reactjs authentication devise

非常感谢您查看我的问题。我正在构建一个Rails API,它与不同服务器上的React前端一起使用。我正在使用Devise Token Auth gem,并且能够成功登录,注销,并且可以毫无问题地获取多个资源的请求。为了处理更改令牌,我正在更新每个请求的标头。

我遇到的问题是当我尝试发出PUT请求更新资源时,在这种情况下我得到一个401.完整的错误消息:

Started PUT "/api/stores/3/orders/1" for 127.0.0.1 at 2017-07-12 16:00:05 -0400
Processing by Api::OrdersController#update as HTML
  Parameters: {"order"=>{"id"=>1, "provider_notes"=>"tailor notes"}, "headers"=>{"client"=>"YVa0NIlxAdm6BLQXk0xeJw", "access-token"=>"bNc9BB0TgICIJzGfM4H_6A", "uid"=>"joe@joestailor.com"}, "store_id"=>"3", "id"=>"1"}
Can't verify CSRF token authenticity.
Filter chain halted as :authenticate_user! rendered or redirected
Completed 401 Unauthorized in 1ms (Views: 0.1ms | ActiveRecord: 0.0ms)

检查后,错误消息中打印的访问令牌实际上是我从上一个请求获得的令牌,所以它应该是好的。这是我正在使用的控制器。我无法通过authenticate_user!行动之前。

class Api::OrdersController < ApplicationController
  before_action :authenticate_user!
  before_action :set_order, only: [:show, :update]

  def index
    render :json => current_user.store.open_orders.as_json(include: [:customer], methods: [:alterations_count])
  end

  def show
    render :json => @order.as_json(include: [:customer, :items => {include: :item_type}])
  end

  def update
    if @order.update(order_params)
      render :json => @order
      .as_json(include: [:customer, :items => {include: :item_type}])
    else
      byebug
    end
  end

  private

  def set_order
    @order = Order.find(params[:id])
  end

  def order_params
    if current_user.tailor?
      params.require(order).permit(:requester_notes, :arrived, :fulfilled)
    end
  end
end

为什么put请求可能与我一直使用的get请求(对于同一个控制器)的工作方式不同?任何使用Devise Auth Token解决这个问题的建议都会很棒。谢谢。

2 个答案:

答案 0 :(得分:1)

你使用的是:authenticate_user!从设计?

如果是的话,它无法为api工作 你需要创建自己的帮助方法

你可以把它放在你的api application_controller / model_controller

或创建一个模块并将其包含在您需要的任何地方

然后将before操作更改为authenticate_with_token!

  def current_user_api
    @current_user ||= User.find_by(auth_token: request.headers['Authorization'])
  end

  def user_signed_in_api?
    current_user_api.present?
  end

  def authenticate_with_token!
    render json: { errors: "Not authenticated" },
      status: :unathorized unless user_signed_in_api? 
  end
本书第5章将为您提供帮助 http://apionrails.icalialabs.com/book/chapter_five

Can't verify CSRF token authenticity.

你可以将它放在你的应用程序控制器中

  protect_from_forgery with: :null_session
  skip_before_action :verify_authenticity_token, if: :json_request?

  protected
    def json_request?
      request.format.json?
    end

答案 1 :(得分:0)

如果要使用:authenticate_user!或类似名称,请确保传递所有必需的参数:

  • 访问令牌
  • 到期
  • 令牌类型
  • uid
  • 客户

您似乎缺少了expirytoken-type

假设令牌和凭据有效,这将导致对用户进行身份验证并按预期设置current_user

注意:这些标头需要在您的CORS配置中公开:

Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins '*'
    resource "*",
         expose: %w[access-token expiry token-type uid client],
         headers: :any,
         methods: :any
  end
end

另一个注意事项:如果将devise端点安装在api内,则需要调用其他:authenticate_user!方法。

示例:

namespace :api, defaults: { format: 'json' } do
  namespace :v1 do
    mount_devise_token_auth_for 'User', at: 'auth'

    # API routing and resources
  end
end

然后,您需要致电:authenticate_api_v1_user!

示例:

 class Api::V1::ApiController < ApplicationController
   before_action :authenticate_api_v1_user!
 end