Rails authenticity_token 向 API::V1 模块控制器提交请求时无法验证

Rails authenticity_token cannot be verified when submitting requests to API::V1 module controllers

我在使用 Rails 5 时遇到了一个非常奇怪的问题。我有两个控制器,第一个是 users_controller,第二个是 api/v1/users_controller。这两个控制器都有一个 register 动作。我正在尝试 post 向这两个控制器发送一个表单。此表单创建如下,

 <%= form_tag('v2/register/user', {id: "add-user-form", class: "jiffle-form", role: "form"}) do%>
   #form body
   <%= submit_tag("Resigter", data: {i18n: "register"}, class:  "btn btn-lg btn-block btn-blue", id: "add-user", type: "submit") %>
<% end %>

路线,

post "register" => "users#create", :as => "user_registeration_submit"
post "v2/register/user" => "api/v1/users#create"

当我使用 /register url 提交表单时,它得到了成功处理。但是,当我使用 v2/register/user url 提交表单时,出现 Can't verify CSRF token authenticity 错误。

参数

Processing by UsersController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"ADNTIp9alRB/ujRhkoqNuDkzdW6ANfcl/MbPjGLwVd6nwVuG5oi+uVhE9MeZo+1MeyKLbwZYNV31Vy/VH3M2bg==", "sfdc_token"=>"",
 "email"=>"[FILTERED]", "first_name"=>"kjl", "last_name"=>"jk", "contact_no"=>"894892849", "company_name"=>"j", "title"=>"kj",
 "internal_366vagan2"=>"", "consent"=>"true",
 "commit"=>"Register"}

当我使用 ajax 将表单提交给 api/v1/users_controller 并在请求中使用 X-CSRF-TOKEN header 时,它工作正常.

我要在哪里进行更改才能使我的 api/v1 控制器正常工作?

你可以简单地写成application_controller.rb

   protect_from_forgery with: :exception, unless: -> { request.format.json? }

并在 routes.rb 文件

中设置默认格式为 json

但更好的方法:

在您的情况下,您必须创建两个命名空间,一个用于处理 API 响应,第二个用于处理 FORM。相应地在 routes.rb 文件中使用命名空间。以及相应地从 ApplicationController 继承的两个不同的基本控制器。

对于API

class Api::V1::ApplicationController < ApplicationController
   protect_from_forgery with: :exception, unless: -> { request.format.json? }
end

并在 routes.rb 文件

中设置默认格式为 json
 resources :tasks, defaults: {format: :json}

对于表单视图

使用默认设置,或

class Admin::AdminController < ApplicationController
   protect_from_forgery with: :exception
end
#In this case, comment it from main application_controller.rb file:protect_from_forgery with: :exception

注意:这里的Admin和Api是两个命名空间。 routes.rb 文件将如下所示:

#For admin
namespace :admin do

end 

#For Api
namespace :api do
    scope module: :v1 do

    end
end 

希望它会起作用:)