简体   繁体   English

Devise Token Auth 不会为 PUT 路由进行身份验证

[英]Devise Token Auth Will Not Authenticate for PUT Route

Hi thanks for viewing my question.您好,感谢您查看我的问题。 I'm building out a Rails API which works with a React front end on a different server.我正在构建一个 Rails API,它与不同服务器上的 React 前端一起工作。 I'm using the Devise Token Auth gem, and am able to successfully log in, log out, and make get requests for multiple resources without any problems.我正在使用 Devise Token Auth gem,并且能够成功登录、注销并毫无问题地获取多个资源的请求。 To handle the changing tokens I am updating the headers on each request.为了处理不断变化的令牌,我正在更新每个请求的标头。

The problem I am running into is when I try to make a PUT request to update a resource, in which case I get a 401. Full error message:我遇到的问题是当我尝试发出 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)

After checking, the access-token printed in the error message is in fact the token i got from the last request, so it should be good.经检查,报错信息中打印的access-token其实就是我上次请求得到的token,应该没问题。 Here's the controller I am working with.这是我正在使用的控制器。 I'm not able to get passed the authenticate_user.我无法通过 authenticate_user。 before action.行动前。

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

Any reason why a put request might work differently than the get requests I've been using (for this same controller)? put 请求的工作方式可能与我一直使用的 get 请求(对于同一控制器)不同的任何原因? Any advice to get around this with the Devise Auth Token would be awesome.任何使用 Devise Auth Token 解决这个问题的建议都会很棒。 Thanks.谢谢。

are you using:authenticate_user?你在使用:authenticate_user 吗? from devise?从设计?

if yes, it can't work for api you need create your own helper method如果是,它不适用于你需要创建自己的辅助方法的 api

you can put it in your api application_controller/model_controller你可以把它放在你的 api application_controller/model_controller

or cretae a module and include it wherever you need或创建一个模块并将其包含在您需要的任何地方

then change the before action into authenticate_with_token!然后将之前的操作更改为 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

this book chapter 5 will help you http://apionrails.icalialabs.com/book/chapter_five本书第 5 章将为您提供帮助http://apionrails.icalalabs.com/book/chapter_five

and for Can't verify CSRF token authenticity.以及Can't verify CSRF token authenticity.

you can put this in your application controller你可以把它放在你的应用程序控制器中

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

  protected
    def json_request?
      request.format.json?
    end

If you want to use :authenticate_user!如果你想使用:authenticate_user! or similar, then make sure to pass in all the necessary parameters:或类似的,然后确保传递所有必要的参数:

  • access-token访问令牌
  • expiry到期
  • token-type令牌类型
  • uid uid
  • client客户

It looks like you were missing expiry and token-type .看起来您缺少expirytoken-type

This will result in the user being authenticated and the current_user being set as expected, assuming the token and credentials are valid.假设令牌和凭据有效,这将导致对用户进行身份验证并按预期设置current_user

Note: these headers my need to be exposed in your CORS configuration:注意:我需要在您的 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

Another Note: If you mounted your devise endpoint inside the api, then you will need to call a different :authenticate_user!另一个注意事项:如果你在 api 中安装了你的设计端点,那么你将需要调用一个不同的:authenticate_user! method.方法。

example:例子:

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

    # API routing and resources
  end
end

Then you would need to call :authenticate_api_v1_user!然后你需要调用:authenticate_api_v1_user! instead.反而。

example:例子:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM