Rails 具有多个提交操作的表单具有无效的身份验证令牌(CSRF 错误)

Rails form with multiple submit actions has invalid auth token (CSRF error)

我有一个rails表格:

<%= form_with(model: activity, method: 'POST', url: retry_failed_post_path, class: 'px-4', data: { turbo: false }) do |form| %>
  <div class="grid grid-cols-1 gap-4">
    <%= form.hidden_field :id, value: activity.id %>
    <%= form.labeled_text_field :response, name: '', readonly: true, label: 'Response from...', value: 'Invalid or expired token' %>

    <% token_tag %>
    <div class="flex flex-row space-x-2 items-center">
      <%= form.submit 'Retry', class: 'btn btn-primary' %>
      <%= form.submit 'Remove from Queue', class: 'btn btn-primary btn-outline', formaction: remove_failed_post_path %>
      <div class="tooltip" data-tip="Failed posts are only resolved by trying to publish the content again or removing the post from the failed posts queue.">
        <%= iconhelper :info, size: '8' %>
      </div>
    </div>
  </div>
<% end %>

结果如下HTML:

<form class="px-4" data-turbo="false" action="/failed/retry" accept-charset="UTF-8" method="post">
  <input name="utf8" type="hidden" value="✓">
  <input type="hidden" name="authenticity_token" value="puKpnE6rnoeUnrWco8f+lesCjygvjPn2A7e70Wz0ak8dirurzYYtE2JjqagneA7naJsszk2BEVF9QI7nd5YQwA==">
  <div class="grid grid-cols-1 gap-4">
    <input value="471386a9-c54e-4bd3-9a6d-c8392d130cd5" type="hidden" name="activity[id]">
    <div class="">
      <label class="field-label">
        <span class="field-label-span">Response from...</span>
      </label>
      <div class="field-input-wrapper">
        <input name="" readonly="readonly" value="Invalid or expired token" type="text" class="sa-field-input">
      </div>
    </div>

    <div class="flex flex-row space-x-2">
      <input type="submit" name="commit" value="Retry" class="btn btn-primary" data-disable-with="Retry">
      <input type="submit" name="commit" value="Remove" class="btn btn-primary btn-outline" formaction="/new/failed/remove" data-disable-with="Remove">
    </div>
  </div>
</form>

当使用第一个提交按钮时,我的表单提交正常,没有任何问题。但是,当我使用第二个 submit 按钮(使用 formation 覆盖)提交时,我收到无效的身份验证令牌错误。有人可以帮助解释为什么以及如何解决它吗?

[0ba3ef85-2fa4-474d-82d2-f3f03fc8046f] ActionController::InvalidAuthenticityToken excluded from capture: DSN not set
[0ba3ef85-2fa4-474d-82d2-f3f03fc8046f]   
[0ba3ef85-2fa4-474d-82d2-f3f03fc8046f] ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
[0ba3ef85-2fa4-474d-82d2-f3f03fc8046f]   
[0ba3ef85-2fa4-474d-82d2-f3f03fc8046f] actionpack (6.1.4) lib/action_controller/metal/request_forgery_protection.rb:211:in `handle_unverified_request'
[0ba3ef85-2fa4-474d-82d2-f3f03fc8046f] actionpack (6.1.4) lib/action_controller/metal/request_forgery_protection.rb:243:in `handle_unverified_request'
[0ba3ef85-2fa4-474d-82d2-f3f03fc8046f] actionpack (6.1.4) lib/action_controller/metal/request_forgery_protection.rb:238:in `verify_authenticity_token'
[0ba3ef85-2fa4-474d-82d2-f3f03fc8046f] activesupport (6.1.4) lib/active_support/callbacks.rb:427:in `block in make_lambda'
[0ba3ef85-2fa4-474d-82d2-f3f03fc8046f] activesupport (6.1.4) lib/active_support/callbacks.rb:198:in `block (2 levels) in halting'
[0ba3ef85-2fa4-474d-82d2-f3f03fc8046f] actionpack (6.1.4) lib/abstract_controller/callbacks.rb:34:in `block (2 levels) in <module:Callbacks>'

所以,我能够找出问题所在。我正在使用 Hotwire/Turbo,并且将 data : { turbo: false } 包含在表单中会删除所有 AJAX 位——确保 CSRF 令牌不会 change/update 基于表单动作变化...

所以,结果 ERB/HTML:

<%= form_for(model: activity, builder: CustomBuilder, url: retry_failed_path, method: :POST, class: 'px-4') do |form| %>
  <div class="grid grid-cols-1 gap-4">
    <%= form.hidden_field :id, value: activity.id %>
    <%= form.labeled_text_field :response, name: '', readonly: true, label: 'Response from...', value: 'Invalid or expired token' %>

    <div class="flex flex-row space-x-2 items-center">
      <%= form.submit 'Retry', class: 'btn btn-primary' %>
      <%= form.button 'Remove', class: 'btn btn-primary btn-outline', formaction: remove_failed_path %>
      <div class="tooltip" data-tip="Failed posts are only resolved by trying to publish the content again or removing the post from the failed posts queue.">
        <%= iconhelper :info, size: '8' %>
      </div>
    </div>
  </div>
<% end %>