InvalidAuthenticityToken

下面是一个错误,是由我的 Rails 应用程序中的一个表单引起的:

Processing UsersController#update (for **ip** at 2010-07-29 10:52:27) [PUT]
Parameters: {"commit"=>"Update", "action"=>"update", "_method"=>"put", "authenticity_token"=>"ysiDvO5s7qhJQrnlSR2+f8jF1gxdB7T9I2ydxpRlSSk=", **more parameters**}


ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):

每个非 get请求都会发生这种情况,如您所见,authenticity_token就在那里。

277902 次浏览

真实性令牌是在视图中生成的一个随机值,用于证明请求是从站点上的表单提交的,而不是从其他地方提交的。这可以防止 CSRF 的攻击:

Http://en.wikipedia.org/wiki/cross-site_request_forgery

检查看看那个客户端/IP 是谁,看起来他们正在使用您的网站而没有加载您的意见。

如果需要进一步调试,可以从这个问题开始: 理解 Rails 真实性令牌

编辑解释: 这意味着他们正在调用这个动作来处理你的表单提交,而不需要在你的网站上呈现你的表单。这可能是恶意的(比如发布垃圾邮件评论) ,也可能表明客户试图直接使用您的 Web 服务 API。你是唯一一个可以根据你的产品性质和分析你的需求来回答这个问题的人。

我有同样的问题,但与页面缓存。使用陈旧的真实性令牌和所有使用 post/put/delete 方法的操作来缓冲页面,这些方法被认为是伪造尝试。向用户返回错误(422 Unprocessable Entity)。

Rails 3的解决方案:
地址:

 skip_before_filter :verify_authenticity_token

或者正如 Rails 4中指出的那样:

 skip_before_action :verify_authenticity_token

在进行缓存的页面上。

正如@tobulkeh 所说,这不是 :index:show操作的漏洞,但是要注意在 :put:post操作中使用这个漏洞。

例如:

 caches_page :index, :show
skip_before_filter :verify_authenticity_token, :only => [:index, :show]

参考资料: http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection/ClassMethods.html

由 barlop-Rails 4.2添加的注意事项不赞成跳过之前的过滤器,而支持跳过之前的操作 https://guides.rubyonrails.org/4_2_release_notes.html“ * _ filter 系列方法已经从文档中删除。我们不鼓励使用它们,而鼓励使用 * _ action 系列方法

对于 铁路6(正如“ collimarco”指出的那样) ,您可以使用 skip_forgery_protection,并且对于不使用会话数据的 REST API 使用它是安全的。

问题通过从2.3.8降级到2.3.5来解决(以及臭名昭著的“你正在被重定向”问题)

对我来说,Rails 4下的这个问题的原因是一个缺失,

<%= csrf_meta_tags %>

在我的主要应用程序布局。我不小心删除了它时,我重写了我的布局。

如果这不是在主布局中,您将需要它在任何页面,您想要一个 CSRF 令牌上。

我在 javascript 调用中遇到了这个问题,我只需要在 application.js 文件中添加 jquery _ ujs 就可以解决这个问题。

我找到了解决办法。

当您定义自己的 html 表单时,可能会忘记包含控制器出于安全原因所需的身份验证令牌字符串。但是当您使用 Rails 生成器创建表单时,您会得到如下内容:

<form accept-charset="UTF-8" action="/login/signin" method="post">
<div style="display:none">
<input name="utf8" type="hidden" value="&#x2713;">
<input name="authenticity_token" type="hidden"
value="x37DrAAwyIIb7s+w2+AdoCR8cAJIpQhIetKRrPgG5VA=">
.
.
.
</div>
</form>

因此,解决这个问题的方法是手动添加 enticity _ token 字段,或者使用 Rails 表单助手,而不是删除、降级或升级 Rails 生成的代码。

我有这个问题,原因是因为我复制并粘贴了一个控制器到我的应用程序。我需要把 ApplicationController改成 ApplicationController::Base

这个错误有几个原因(与 Rails 4有关)。

1. 检查页面布局中的 <%= csrf_meta_tags %>

2.如果使用带有 remote: true选项的 form_for助手,检查真实性令牌将通过 AJAX 调用发送。如果不能,可以在表单块中包含 <%= hidden_field_tag :authenticity_token, form_authenticity_token %>行。

3.如果从缓存页面发送请求,使用 片段缓存排除发送请求的页面的一部分,例如 button_to等,否则令牌将过期/无效。

我不想取消证监会的保护。

如果您已经完成了 rake rails:update或最近更改了 config/initializers/session_store.rb,这可能是浏览器中旧 cookie 的症状。希望这是在 dev/test 中完成的(对我来说是这样) ,您可以清除所有与相关域相关的浏览器 cookie。

如果这是在生产环境中,并且您更改了 key,那么可以考虑将其更改回使用旧 cookie (<-just 臆测)。

安装中

gem 'remotipart'

能帮上忙

我们遇到了同样的问题,但是注意到它只适用于使用 http://而不适用于 https://的请求。原因是 session _ store 的 secure: true:

Rails.application.config.session_store(
:cookie_store,
key: '_foo_session',
domain: '.example.com',
secure: true
)

通过使用 HTTPS ~ Everywhere 修复:)

我在本地主机上也遇到了同样的问题。我已经更改了应用程序的域名,但在 URL 和主机文件中仍然有旧的域名。更新了我的浏览器书签和主机文件,使用新的域名,现在一切工作正常。

只是增加了 authenticity_token的形式为我修复它。

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>

也许您已经为 HTTPS 设置了 NGINX,但是您的证书是无效的? 我过去也遇到过类似的问题,将 http 重定向到 https 解决了这个问题

对于 Rails5,最好添加 跳过 verify_authentication_token比跳过 protect_from_forgery prepend: true

我已经检查了 <% = csrf _ meta _ tag% > 是否存在,并且在浏览器中清除 cookies 对我来说是有用的。

ActionController::InvalidAuthenticityToken也可能由错误配置的反向代理引起。如果在堆栈跟踪中,您得到一个类似于 Request origin does not match request base_url的行,那么就是这种情况。

当使用反向代理(如 nginx)作为 HTTPS 请求的接收方并将未加密的请求传输到后端(如 Rails 应用程序)时,后端(更具体地说: Rack)希望一些头文件包含有关原始客户端请求的更多信息,以便能够应用各种处理任务和安全措施。

更多详情请点击这里: https://github.com/rails/rails/issues/22965

DR: 解决方案是添加一些头:

upstream myapp {
server              unix:///path/to/puma.sock;
}


location / {
proxy_pass        http://myapp;
proxy_set_header  Host $host;
proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header  X-Forwarded-Proto $scheme;
proxy_set_header  X-Forwarded-Ssl on; # Optional
proxy_set_header  X-Forwarded-Port $server_port;
proxy_set_header  X-Forwarded-Host $host;
}

根据 Chrome Lighthouse 关于更快应用程序加载的建议,我已经异步了我的 Javascript:

views/layout/application.html.erb

<%= javascript_include_tag 'application', 'data-turbolinks-track' => 'reload', async: true %>

这打破了一切,并得到了我的远程表单的令牌错误。删除 async: true修复了这个问题。

//= require rails-ujs

进去

\app\assets\javascripts\application.js

这个答案对于 RubyonRails 来说更加具体,但是希望它能对某些人有所帮助。

每个非 GET 请求都需要包含 CSRF 令牌。如果您习惯于使用 JQuery,Rails 有一个名为 jquery-ujs的帮助器库,它构建在 JQuery 之上,并添加了一些隐藏的功能。它所做的事情之一是在每个 ajax请求中自动包含 CSRF 令牌。看这里.

如果你像我一样切换,你可能会发现自己犯了一个错误。您可以手动提交令牌,或者使用另一个库来帮助从 DOM 中获取令牌。有关更多细节,请参见 这篇文章

在 Rails 5中,我们需要添加2行代码

    skip_before_action :verify_authenticity_token
protect_from_forgery prepend: true, with: :exception

对于 Development 环境,我在 Rails 6中尝试了许多这样的尝试来修复这个问题。他们都没帮上忙。因此,如果这些建议对你都不管用,试试下面的方法。

我找到的唯一解决方案是在/tmp 文件夹中添加一个 txt 文件。

在应用程序的根目录中,运行:

touch tmp/caching-dev.txt

或者在/tmp 文件夹中以该名称手动创建文件。由于这为我解决了这个问题,我认为问题的根源是缓存冲突。

在我的控制台运行 rails dev:cache为我修复了这个问题! (Rails 6)

我认为这可能与 Turbolinks 有关,但 CSRF 似乎只有在本地缓存为 启用时才能工作。

这种情况发生在我对应用程序的注册过程(与多个用户进行注册/登录)进行手动测试时。

一个非常简单和实用的解决方案可能是做我所做的,并使用不同的浏览器(或匿名如果使用铬)。

在我的案例中,这是一个比禁用安全特性更好的 强大解决方案! !

当我从 Rails 4.0升级到4.2时,就发生了这种情况。

verified_request?的4.2实现查看 request.headers['X-CSRF-Token'],而我的4.0应用程序得到的头文件是 X-XSRF-TOKEN。我的 ApplicationController 中的一个快速修复是添加这个函数:

  def verify_authenticity_token
request.headers['X-CSRF-Token'] ||= request.headers['X-XSRF-TOKEN']
super
end

我在 Rails 6中遇到了类似的错误。在尝试了上面的解决方案之后,我做了一个表单检查,发现我在表单中使用了 <button>.....</button> HTML 标记,而不是通过 Rails

<% = form
表单助手提交。更改为表单助手解决了这个问题。