非常感谢您查看我的问题。我正在构建一个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解决这个问题的建议都会很棒。谢谢。
答案 0 :(得分:1)
如果是的话,它无法为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!
或类似名称,请确保传递所有必需的参数:
您似乎缺少了expiry
和token-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