ruby-on-rails - 使用 form_with 时出现“ActionController::InvalidAuthenticityToken”错误
问题描述
我有一个看起来像这样的表格:
<%= form_with(url: star.starname, method: :post, local: true) do |f| %>
<% star.availabilities.each do |avail| %>
<%= f.label avail.time_slot %>
<%= radio_button_tag(:time_slot, avail.time_slot) %> <br>
<% end %>
<%= f.submit "Create" %>
<% end %>
表单提交后立即:
笔记:
- 这发生在应用程序(而不是 API)中,因此会话很重要,因此必须保持 CSRF 保护。
- 该问题出现在 chrome、incognito 和 safari 中。
- 我尝试使用不同的用户登录并清除 cookie(以防它是由过时的令牌引起的)
更多的错误信息:
Started POST "/talljohn" for ::1 at 2020-09-16 10:06:21 +1000
Processing by StarsController#book as HTML
Parameters: {"authenticity_token"=>"P++4a+giwUBqZgCLfMwqKpMu0EGitd8zTOi5RWsnxpKlNcjiuU6hd3ebbIC/IOxlL74RJIvrq+yDuA1ZtfcvFw==", "time_slot"=>"2020-09-16 01:00:00 UTC", "commit"=>"Create", "starname"=>"talljohn"}
Can't verify CSRF token authenticity.
Completed 422 Unprocessable Entity in 1ms (ActiveRecord: 0.0ms | Allocations: 655)
ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
actionpack (6.0.3.2) lib/action_controller/metal/request_forgery_protection.rb:215:in `handle_unverified_request'
actionpack (6.0.3.2) lib/action_controller/metal/request_forgery_protection.rb:247:in `handle_unverified_request'
devise (4.7.2) lib/devise/controllers/helpers.rb:255:in `handle_unverified_request'
actionpack (6.0.3.2) lib/action_controller/metal/request_forgery_protection.rb:242:in `verify_authenticity_token'
activesupport (6.0.3.2) lib/active_support/callbacks.rb:428:in `block in make_lambda'
activesupport (6.0.3.2) lib/active_support/callbacks.rb:200:in `block (2 levels) in halting'
actionpack (6.0.3.2) lib/abstract_controller/callbacks.rb:34:in `block (2 levels) in <module:Callbacks>'
activesupport (6.0.3.2) lib/active_support/callbacks.rb:201:in `block in halting'
更新
我恢复到表单的最后一个工作版本,它与上面完全相同,但没有, local: true
. 然后它突然起作用了!(没有错误)。
我认为local: true
(或remote: false
)只是关闭了 ajax 表单提交。所以我不明白为什么这会产生任何影响(或与 CSRF 有任何关系),这两个方面似乎是不相关的,并且不清楚为什么这两个概念会对彼此产生任何影响
更新 2
后来我意识到另一个未触及的以前工作的表单也产生了这个错误。它没有以任何方式改变。我在chrome incognito中尝试过,它产生了错误。半小时后(没有更改任何代码)我在同一个浏览器中再次尝试它并且它工作。这种(非常)奇怪的行为让我觉得这与会话、cookie 或缓存有关。如果我进一步了解,我会报告
更新 3
在阅读了莎拉添加protect_from_forgery prepend: true
到应用程序控制器的解决方案后(我在之前和之后都尝试过before_action :authenticate_user!
),日志中出现相同的错误消息,POST 请求没有被执行,但应用程序重定向到主页。即在 POST 上我看到:
Can't verify CSRF token authenticity.
Completed 401 Unauthorized in 1ms (ActiveRecord: 0.0ms | Allocations: 444)
Started GET "/users/sign_in" for ::1 at 2020-09-17 21:08:42 +1000
Processing by Devise::SessionsController#new as HTML
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
Redirected to http://localhost:3000/
Filter chain halted as :require_no_authentication rendered or redirected
Completed 302 Found in 3ms (ActiveRecord: 0.5ms | Allocations: 1900)
更新 4
我试图手动清除 rails 片段缓存(使用Rails.cache.clear
)。但是清除片段缓存之前/之后的结果完全相同。
解决方案
我记得遇到过这样的事情并在解决它protect_from_forgery prepend: true
之前添加任何用户身份验证。ApplicationController
推荐阅读
- django - 链接到 django 密码重置不显示
- flutter - Flutter-如何从 FlutterSlider (flutter_xlider) 中获取 currentValue
- c - 用一个循环和一个管道在 C 中实现无限管道
- testing - 在 Mac 上使用 Jenkins 的 Testcafe:node_modules/.bin/testcafe:没有这样的文件或目录
- c++ - 为什么不能在 switch 中声明字符串函数?
- python-3.x - 如何使用 python 在远程服务器中执行命令?
- r - 在 R 中,当我加载以日期序列作为标题的数据帧时,如何保留日期的原始格式?
- java - Jackson JsonMappingException .No String-argument 构造函数/工厂方法从字符串值反序列化
- java - 从单独的主类 Java 打印 ArrayList
- android - React Native android 不使用 react-native-device-info 编译