简体   繁体   English

无法通过React Native应用程序调用在Rails API中验证CSRF令牌

[英]Can't verify CSRF token in Rails API from a React Native app call

I am trying to make a post request from a React Native app to a Rails app (API) 我正在尝试从React Native应用程序向Rails应用程序(API)发出发布请求

Some settings that I have followings: 我具有以下一些设置:

I am using the gem rack-cors to handle CSRF issue. 我正在使用gem rack-cors处理CSRF问题。

In application.rb application.rb

config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins '*'
    resource '*',
    headers: :any,
    methods: [:get, :post, :patch, :delete, :options],
    expose: ['access-token', 'expiry', 'token-type', 'uid', 'client']
  end
end

I am allowing everything for the time being, because for now I am just doing API calls, later on I will put the domain. 我暂时允许所有操作,因为现在我只是在进行API调用,稍后我将放置域。

Also, I deactivated protect from forgery, so that the CSRF check is not made, and requests are just checked through the access token 另外,我停用了防止伪造的功能,因此不会进行CSRF检查,而只是通过访问令牌检查请求

class ApplicationController < ActionController::Base
  include DeviseTokenAuth::Concerns::SetUserByToken

  # protect_from_forgery

In devise_token_auth.rb I added: devise_token_auth.rb我添加了:

config.change_headers_on_each_request = false

In my controller, I added: 在我的控制器中,我添加了:

class Api::V1::TrainingsController < ApplicationController
  before_action :authenticate_user!

I am using the gem 'devise_token_auth' , so in my User model I have: 我正在使用gem 'devise_token_auth' ,因此在我的用户模型中,我有:

class User < ActiveRecord::Base
  has_many :trainings

  extend Devise::Models
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  include DeviseTokenAuth::Concerns::User
end

The routes are following, but just the import one is the important: 遵循以下路线,但是重要的是导入路线:

Rails.application.routes.draw do
  mount_devise_token_auth_for 'User', at: 'auth'
  root to: 'pages#home'
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
  namespace :api, defaults: { format: :json } do
    namespace :v1 do
      resources :trainings, only: [ :index, :show, :create ]
      post 'import', to: "trainings#import"
    end
  end
end

I could login, since no token is required, you get the token. 我可以登录,因为不需要令牌,您就可以获取令牌。 Here it begins the React Native story. 从这里开始了React Native的故事。 I have the token that the server sends, and I do the call: 我有服务器发送的令牌,然后执行呼叫:

    const rawResponse = await fetch('https://plankorailsfour.herokuapp.com/api/v1/import', {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
      'Access-Token': auth.accessToken,
      'token-type': 'Bearer',
      'client': auth.client,
      'uid': '1',
      'X-Requested-With': 'XMLHttpRequest'
    },
    body: JSON.stringify(bodyRequest)
  })
  const headers = await rawResponse.headers
  const data = await rawResponse.json()

I've tried to pass the authentication token sent from the backend to the call, but I keep getting same error message when I do the import call: 我尝试将后端发送的身份验证令牌传递给调用,但是在执行import调用时,我始终收到相同的错误消息:

Started POST "/api/v1/import" for 46.128.35.112 at 2019-07-23 05:04:32 +0000
2019-07-23T05:04:32.586008+00:00 app[web.1]: I, [2019-07-23T05:04:32.585930 #4]  INFO -- : [dd02c2bc-1367-474a-81a3-f60740e7a661] Processing by Api::V1::TrainingsController#import as JSON
2019-07-23T05:04:32.586079+00:00 app[web.1]: I, [2019-07-23T05:04:32.586010 #4]  INFO -- : [dd02c2bc-1367-474a-81a3-f60740e7a661]   Parameters: {"uid"=>"1", "training"=>{}}
2019-07-23T05:04:32.586319+00:00 app[web.1]: W, [2019-07-23T05:04:32.586199 #4]  WARN -- : [dd02c2bc-1367-474a-81a3-f60740e7a661] Can't verify CSRF token authenticity.
2019-07-23T05:04:32.586567+00:00 app[web.1]: I, [2019-07-23T05:04:32.586508 #4]  INFO -- : [dd02c2bc-1367-474a-81a3-f60740e7a661] Completed 422 Unprocessable Entity in 0ms (ActiveRecord: 0.0ms)
2019-07-23T05:04:32.587644+00:00 app[web.1]: F, [2019-07-23T05:04:32.587566 #4] FATAL -- : [dd02c2bc-1367-474a-81a3-f60740e7a661]
2019-07-23T05:04:32.587718+00:00 app[web.1]: F, [2019-07-23T05:04:32.587648 #4] FATAL -- : [dd02c2bc-1367-474a-81a3-f60740e7a661] ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
2019-07-23T05:04:32.587796+00:00 app[web.1]: F, [2019-07-23T05:04:32.587726 #4] FATAL -- : [dd02c2bc-1367-474a-81a3-f60740e7a661]
2019-07-23T05:04:32.587928+00:00 app[web.1]: F, [2019-07-23T05:04:32.587827 #4] FATAL -- : [dd02c2bc-1367-474a-81a3-f60740e7a661] vendor/bundle/ruby/2.4.0/gems/actionpack-5.2.1/lib/action_controller/metal/request_forgery_protection.rb:211:in `handle_unverified_request'
2019-07-23T05:04:32.587930+00:00 app[web.1]: [dd02c2bc-1367-474a-81a3-f60740e7a661] vendor/bundle/ruby/2.4.0/gems/actionpack-5.2.1/lib/action_controller/metal/request_forgery_protection.rb:243:in `handle_unverified_request'
2019-07-23T05:04:32.587931+00:00 app[web.1]: [dd02c2bc-1367-474a-81a3-f60740e7a661] vendor/bundle/ruby/2.4.0/gems/devise-4.6.2/lib/devise/controllers/helpers.rb:255:in `handle_unverified_request'
2019-07-23T05:04:32.587932+00:00 app[web.1]: [dd02c2bc-1367-474a-81a3-f60740e7a661] vendor/bundle/ruby/2.4.0/gems/actionpack-5.2.1/lib/action_controller/metal/request_forgery_protection.rb:238:in `verify_authenticity_token'

Why is Rails still checking the CSRF token if I deactivated the check, commenting out the protect_from_forgery method? 如果我取消了检查并注释掉了protect_from_forgery方法,为什么Rails仍在检查CSRF令牌?

Why do I have a ActionController::InvalidAuthenticityToken if I am passing in the header the Access-Token . 如果我在标头中传递Access-Token为什么ActionController::InvalidAuthenticityToken有一个ActionController::InvalidAuthenticityToken The name of the key I think is right. 我认为密钥的名称是正确的。

I would say this is happening because you are sending the access token in the CSRF token header. 我会说这是因为您正在CSRF令牌标头中发送访问令牌。 If I am not wrong, there are two completely different tokens on the table: 如果我没有记错的话,表上有两个完全不同的标记:

  1. Access Token . 访问令牌 Handled by the devise_token_auth gem and passed inside Access-Token header. devise_token_auth gem处理并在Access-Token标头内传递。 Is used to authenticate the users. 用于验证用户。

  2. CSRF Token . CSRF令牌 Handled by Rails, and passed inside X-CSRF-Token header. 由Rails处理,并传递到X-CSRF-Token标头中。 Is used to prevent CSRF attacks. 用于防止CSRF攻击。

You will need to send each value in its correspondent header. 您将需要在其对应的标头中发送每个值。

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

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