InvalidAuthenticityToken из формы в Rails 5.2 - PullRequest
0 голосов
/ 23 июня 2019

У меня было работающее приложение Rails5.2, которое нуждалось в реструктуризации базы данных, чтобы улучшить организацию некоторых таблиц.После этого изменения я обнаружил, что некоторые из моих форм не работают последовательно на моей локальной машине с этой ошибкой:

ActionController::InvalidAuthenticityToken in PayBandsController#create

Мне пришлось многое изменить в приложении как часть рефакторинга,Конечно, но тесты все проходят.

Я могу избежать этой проблемы, установив skip_before_action :verify_authenticity_token на соответствующем контроллере (для предыдущих потоков SO), но это, конечно, не очень хорошо.Я хотел бы знать, что является основной причиной, и устранить ее.

  • Форма работает, когда она находится на отдельной странице, помещенной в HTML с render.
  • форма работает, когда я устанавливаю skip_before_action.
  • Форма завершается ошибкой с ошибкой AuthenticityToken, в противном случае - даже если та же самая структура работала раньше.

Это все проверено на моей локальной машинес действительным сеансом.


Форма создается в объекте службы в качестве последней строки таблицы данных (чтобы я мог добавить новые строки в таблицу).Это потенциальная причина проблемы - она ​​отображается в объекте службы, а не в ERB?Хотя этот подход хорошо работал до рефакторинга ...

_table_data += ApplicationController.render(partial: 'datasets/pay_band_numbers_form', locals:{ _dataset_id: _dataset.id, _namespace: _key })

Частичное выглядит следующим образом и, как я уже сказал, работает, если размещено на странице само по себе (например, pay_bands / new), но не там, где нужнобыть (в наборе данных / редактировать):

<%= 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 "&#10004;".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

Контроллер диапазона оплаты:

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

Вся вышеприведенная структура контроллера идентична рабочей версии приложения, прежде чем я возился с даннымимодели!

===

Edit

Я решил проверить заголовки, после еще одного исследования, так что посмотрите, смогу ли я увидеть токензначение.Однако значение токена в теге заголовка meta csrf-token не соответствует ни одному из 3 различных токенов в 3 различных формах на этой странице.Но одна работает в любом случае (простая форма, которая просто render редактируется в шаблоне ERB), а две другие - нет (те, которые render редактируются в объекте службы).Все это оставляет меня в таком же замешательстве, как и раньше!

Кроме того, я попытался удалить Turbolinks из моего файла GemFile и application.js, повторно запустив bundle и rails s, но это не имело никакого значения.

1 Ответ

0 голосов
/ 27 июня 2019

Для дальнейшего использования для тех, у кого возникла та же проблема (ошибки AuthenticityToken для формы, встроенной в вспомогательный или служебный объект), я переместил форму непосредственно в представление и render отредактировал ее там - и проблема исчезла,Я удалил skip_before_action :verify_authenticity_token и теперь все хорошо!

...