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 %>
我有一个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 %>