Rails 5.2 中表单的 InvalidAuthenticityToken
InvalidAuthenticityToken from form in Rails 5.2
我有一个正在运行的 Rails5.2 应用程序,它需要重新构建数据库以改进某些 table 的组织。自此更改以来,我发现我的某些表单在我的本地计算机上始终失败并出现此错误:
ActionController::InvalidAuthenticityToken in PayBandsController#create
当然,作为重构的一部分,我不得不在应用程序中进行很多更改,但测试都通过了。
我可以通过在相关控制器上设置 skip_before_action :verify_authenticity_token
来避免这个问题(根据之前的 SO 线程),但这当然不是一个好的解决方法。我想知道根本原因是什么并消除它。
- 表单在其自己的页面上时有效,在 HTML 中放置
render
。
- 当我设置
skip_before_action
时,该表格有效。
- 表单失败,否则会出现 AuthenticityToken 错误 - 即使之前的结构相同。
这一切都在我的本地机器上使用有效 session.
进行了测试
表单是在服务 object 中创建的,作为数据 table 的最后一行(以便我可以向 table 添加新行)。这是问题的潜在原因吗 - 它是在服务 object 中而不是在 ERB 中呈现的?虽然这种方法在重构之前工作得很好......
_table_data += ApplicationController.render(partial: 'datasets/pay_band_numbers_form', locals:{ _dataset_id: _dataset.id, _namespace: _key })
部分内容如下,正如我所说,如果单独放在页面上(例如 pay_bands/new)但不在需要的地方(在 dataset/edit 上),则可以工作:
<%= form_for (PayBand.new), namespace: _namespace do |f| %>
<%= f.hidden_field :dataset_id, :value => _dataset_id %>
<%= f.text_field :label, :tabindex => 11, :required => true %>
<%= f.number_field :number_women, :tabindex => 12, :required => true %>
<%= f.number_field :number_men, :tabindex => 13, :required => true %>
<%= f.submit "✔".html_safe, :tabindex => 14, class: "button green-button checkmark" %>
<% end %>
涉及的模型有Dataset和PayBand,定义如下
class Dataset < ApplicationRecord
belongs_to :organisation
has_many :pay_bands, inverse_of: :dataset, dependent: :destroy
accepts_nested_attributes_for :pay_bands
default_scope -> { order(created_at: :desc) }
validates :name, presence: true
validates :organisation_id, presence: true
end
class PayBand < ApplicationRecord
belongs_to :dataset
has_many :ages_salaries_genders, inverse_of: :pay_band, dependent: :destroy
validates :dataset_id, presence: true
validates :label, presence: true
end
数据集控制器的相关部分是:
class DatasetsController < ApplicationController
protect_from_forgery with: :exception
load_and_authorize_resource
before_action :authenticate_user!
.
.
.
def edit
@dataset = Dataset.find(params[:id])
end
def update
@dataset = Dataset.find(params[:id])
if @dataset.update_attributes(dataset_params) && dataset_params[:name]
flash[:notice] = "Survey updated"
redirect_back fallback_location: dataset_path(@dataset)
else
flash[:alert] = "Attempted update failed"
redirect_to edit_dataset_path(@dataset)
end
end
.
.
.
private
def dataset_params
params.require(:dataset).permit(:name)
end
end
pay-band 控制器是:
class PayBandsController < ApplicationController
protect_from_forgery with: :exception
# skip_before_action :verify_authenticity_token #DANGEROUS!!!!!
load_and_authorize_resource
before_action :authenticate_user!
def create
@pay_band = PayBand.new(pay_band_params)
if @pay_band.save
flash[:notice] = "Data saved!"
redirect_to edit_dataset_path(Dataset.find(@pay_band.dataset_id))
else
flash[:alert] = "There was an error. Your data was not saved."
redirect_back fallback_location: edit_dataset_path(Dataset.find(pay_band_params[:dataset_id]))
end
end
private
def pay_band_params
params.require(:pay_band).permit(:label, :number_women, :number_men, :avg_salary_women, :avg_salary_men, :dataset_id)
end
end
在我摆弄数据模型之前,以上所有控制器结构都与应用程序的工作版本相同!
===
编辑
经过更多研究,我决定检查 headers,看看我是否能看到令牌值。但是,meta csrf-token
header 标记中的标记值与此页面上 3 种不同形式的 3 种不同标记中的任何一个都不匹配。但是无论如何,一个有效(在 ERB 模板中 render
ed 的简单形式)而其他两个则无效(在服务 object 中 render
ed 的)。这一切让我和以前一样困惑!
此外,我尝试从我的 GemFile 和 application.js 文件、re-running bundle
和 rails s
中删除 Turbolinks,但没有任何区别。
为了以后遇到相同问题的其他人参考(在帮助程序或服务对象中构建的表单的 AuthenticityToken 错误),我将表单直接移动到视图中并在那里 render
编辑它 -问题消失了。我已经删除了 skip_before_action :verify_authenticity_token
,现在一切正常!
我有一个正在运行的 Rails5.2 应用程序,它需要重新构建数据库以改进某些 table 的组织。自此更改以来,我发现我的某些表单在我的本地计算机上始终失败并出现此错误:
ActionController::InvalidAuthenticityToken in PayBandsController#create
当然,作为重构的一部分,我不得不在应用程序中进行很多更改,但测试都通过了。
我可以通过在相关控制器上设置 skip_before_action :verify_authenticity_token
来避免这个问题(根据之前的 SO 线程),但这当然不是一个好的解决方法。我想知道根本原因是什么并消除它。
- 表单在其自己的页面上时有效,在 HTML 中放置
render
。 - 当我设置
skip_before_action
时,该表格有效。 - 表单失败,否则会出现 AuthenticityToken 错误 - 即使之前的结构相同。
这一切都在我的本地机器上使用有效 session.
进行了测试表单是在服务 object 中创建的,作为数据 table 的最后一行(以便我可以向 table 添加新行)。这是问题的潜在原因吗 - 它是在服务 object 中而不是在 ERB 中呈现的?虽然这种方法在重构之前工作得很好......
_table_data += ApplicationController.render(partial: 'datasets/pay_band_numbers_form', locals:{ _dataset_id: _dataset.id, _namespace: _key })
部分内容如下,正如我所说,如果单独放在页面上(例如 pay_bands/new)但不在需要的地方(在 dataset/edit 上),则可以工作:
<%= form_for (PayBand.new), namespace: _namespace do |f| %>
<%= f.hidden_field :dataset_id, :value => _dataset_id %>
<%= f.text_field :label, :tabindex => 11, :required => true %>
<%= f.number_field :number_women, :tabindex => 12, :required => true %>
<%= f.number_field :number_men, :tabindex => 13, :required => true %>
<%= f.submit "✔".html_safe, :tabindex => 14, class: "button green-button checkmark" %>
<% end %>
涉及的模型有Dataset和PayBand,定义如下
class Dataset < ApplicationRecord
belongs_to :organisation
has_many :pay_bands, inverse_of: :dataset, dependent: :destroy
accepts_nested_attributes_for :pay_bands
default_scope -> { order(created_at: :desc) }
validates :name, presence: true
validates :organisation_id, presence: true
end
class PayBand < ApplicationRecord
belongs_to :dataset
has_many :ages_salaries_genders, inverse_of: :pay_band, dependent: :destroy
validates :dataset_id, presence: true
validates :label, presence: true
end
数据集控制器的相关部分是:
class DatasetsController < ApplicationController
protect_from_forgery with: :exception
load_and_authorize_resource
before_action :authenticate_user!
.
.
.
def edit
@dataset = Dataset.find(params[:id])
end
def update
@dataset = Dataset.find(params[:id])
if @dataset.update_attributes(dataset_params) && dataset_params[:name]
flash[:notice] = "Survey updated"
redirect_back fallback_location: dataset_path(@dataset)
else
flash[:alert] = "Attempted update failed"
redirect_to edit_dataset_path(@dataset)
end
end
.
.
.
private
def dataset_params
params.require(:dataset).permit(:name)
end
end
pay-band 控制器是:
class PayBandsController < ApplicationController
protect_from_forgery with: :exception
# skip_before_action :verify_authenticity_token #DANGEROUS!!!!!
load_and_authorize_resource
before_action :authenticate_user!
def create
@pay_band = PayBand.new(pay_band_params)
if @pay_band.save
flash[:notice] = "Data saved!"
redirect_to edit_dataset_path(Dataset.find(@pay_band.dataset_id))
else
flash[:alert] = "There was an error. Your data was not saved."
redirect_back fallback_location: edit_dataset_path(Dataset.find(pay_band_params[:dataset_id]))
end
end
private
def pay_band_params
params.require(:pay_band).permit(:label, :number_women, :number_men, :avg_salary_women, :avg_salary_men, :dataset_id)
end
end
在我摆弄数据模型之前,以上所有控制器结构都与应用程序的工作版本相同!
===
编辑
经过更多研究,我决定检查 headers,看看我是否能看到令牌值。但是,meta csrf-token
header 标记中的标记值与此页面上 3 种不同形式的 3 种不同标记中的任何一个都不匹配。但是无论如何,一个有效(在 ERB 模板中 render
ed 的简单形式)而其他两个则无效(在服务 object 中 render
ed 的)。这一切让我和以前一样困惑!
此外,我尝试从我的 GemFile 和 application.js 文件、re-running bundle
和 rails s
中删除 Turbolinks,但没有任何区别。
为了以后遇到相同问题的其他人参考(在帮助程序或服务对象中构建的表单的 AuthenticityToken 错误),我将表单直接移动到视图中并在那里 render
编辑它 -问题消失了。我已经删除了 skip_before_action :verify_authenticity_token
,现在一切正常!