无法通过 React Native 应用程序调用验证 Rails API 中的 CSRF 令牌
Can't verify CSRF token in Rails API from a React Native app call
我正在尝试从 React Native 应用向 Rails 应用发出 post 请求 (API)
我有以下一些设置:
我正在使用 gem rack-cors
来处理 CSRF 问题。
在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
我暂时允许一切,因为现在我只是在做 API 调用,稍后我会放置域。
此外,我停用了防止伪造的功能,因此不会进行 CSRF 检查,而只是通过访问令牌检查请求
class ApplicationController < ActionController::Base
include DeviseTokenAuth::Concerns::SetUserByToken
# protect_from_forgery
在devise_token_auth.rb
我补充说:
config.change_headers_on_each_request = false
在我的控制器中,我添加了:
class Api::V1::TrainingsController < ApplicationController
before_action :authenticate_user!
我正在使用 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
路线如下,但重要的是导入路线:
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
我可以登录,因为不需要令牌,你得到令牌。 React Native 的故事从这里开始。我有服务器发送的令牌,然后调用:
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()
我尝试将从后端发送的身份验证令牌传递给调用,但是在执行 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'
如果我停用检查并注释掉 protect_from_forgery
方法,为什么 Rails 仍在检查 CSRF 令牌?
如果我传入 header 和 Access-Token
,为什么我会有 ActionController::InvalidAuthenticityToken
。 key的名字我觉得是对的
我会说这是因为您在 CSRF 令牌 header 中发送访问令牌。如果我没记错的话,table:
上有两个完全不同的标记
访问令牌。由 devise_token_auth
gem 处理并在 Access-Token
header 内部传递。用于验证用户。
CSRF 令牌。由 Rails 处理,并在 X-CSRF-Token
header 内部传递。用于防止CSRF攻击。
您需要发送对应的每个值 header。
我正在尝试从 React Native 应用向 Rails 应用发出 post 请求 (API)
我有以下一些设置:
我正在使用 gem rack-cors
来处理 CSRF 问题。
在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
我暂时允许一切,因为现在我只是在做 API 调用,稍后我会放置域。
此外,我停用了防止伪造的功能,因此不会进行 CSRF 检查,而只是通过访问令牌检查请求
class ApplicationController < ActionController::Base
include DeviseTokenAuth::Concerns::SetUserByToken
# protect_from_forgery
在devise_token_auth.rb
我补充说:
config.change_headers_on_each_request = false
在我的控制器中,我添加了:
class Api::V1::TrainingsController < ApplicationController
before_action :authenticate_user!
我正在使用 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
路线如下,但重要的是导入路线:
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
我可以登录,因为不需要令牌,你得到令牌。 React Native 的故事从这里开始。我有服务器发送的令牌,然后调用:
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()
我尝试将从后端发送的身份验证令牌传递给调用,但是在执行 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'
如果我停用检查并注释掉 protect_from_forgery
方法,为什么 Rails 仍在检查 CSRF 令牌?
如果我传入 header 和 Access-Token
,为什么我会有 ActionController::InvalidAuthenticityToken
。 key的名字我觉得是对的
我会说这是因为您在 CSRF 令牌 header 中发送访问令牌。如果我没记错的话,table:
上有两个完全不同的标记访问令牌。由
devise_token_auth
gem 处理并在Access-Token
header 内部传递。用于验证用户。CSRF 令牌。由 Rails 处理,并在
X-CSRF-Token
header 内部传递。用于防止CSRF攻击。
您需要发送对应的每个值 header。