ActionController :: InvalidAuthenticityToken


148

以下是由我的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

Answers:


207

我有同样的问题,但页面已缓存。页面使用过时的真实性令牌进行缓冲,并且所有页面操作都使用方法post / put / delete进行识别,这是伪造尝试。错误(422无法处理的实体)已返回给用户。

Rails 3的解决方案:
添加:

 skip_before_filter :verify_authenticity_token  

或作为Rails 4中指出的“ sagivo”添加:

 skip_before_action :verify_authenticity_token

在进行缓存的页面上。

作为@toobulkeh评论说,这不是一个漏洞: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添加的注释不建议使用skip_before_filter,而建议使用skip_before_action https://guides.rubyonrails.org/4_2_release_notes.html “ * _filter系列方法已从文档中删除。不建议使用* _action系列方法方法族”

对于Rails 6(如“ collimarco”所指出的那样),您可以使用skip_forgery_protection,并且可以安全地将其用于不使用会话数据的REST API。


3
不太可能,您发布之前我不知道caches_page。但我会检查caches_page的,谢谢。
Nikita Rybak 2010年

7
在轨道4中skip_before_action :verify_authenticity_token
Sagiv Ofek

88
这不是漏洞吗?
Quantumpotato 2014年

6
这不是操作上的漏洞:index, :show。但是要警惕将其付诸:put, :post行动!
toobulkeh 2015年

14
尽管我同意有时您有时需要这样做(例如一生中一次),但是您需要意识到自己正在通过禁用安全性来修复安全性。不推荐使用
等效

77

对我来说,在Rails 4下导致此问题的原因不见了,

<%= csrf_meta_tags %>

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

如果这不在主布局中,则您需要CSRF令牌的任何页面上都需要它。


2
我们也收到此错误。但这是断断续续的。这可能是原因,还是不影响每个错误的请求?
瑞安·尼尔·梅斯

@ Ryan-NealMes,如果您的模板缺少该行,则会收到错误消息。因此,您的某些模板可能有它,而其他模板则没有。
詹姆斯·麦克马洪

1
@JamesMcMahon谢谢,我发现我的案件实际上是由用户清除cookie或阻止cookie引起的。从这个问题中学到了负载!
Ryan-Neal Mes 2015年

61

导致此错误的原因有多种(与Rails 4有关)。

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

,如果使用2令牌正在使用AJAX发送支票真伪来电form_for助手与remote: trueoption.If不是你可以包括行<%= hidden_field_tag :authenticity_token, form_authenticity_token %>withing形式块。

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

我不愿意取消csrf保护...


csrf_meta_tags应该在<head>中吗?我如何确定它与涡轮链接不冲突?
闪耀


30

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

http://en.wikipedia.org/wiki/Cross-site_request_forgery

检查一下该客户端/ IP是谁,看起来他们在使用您的网站而不加载您的视图。

如果您需要进一步调试,那么这个问题是一个很好的起点:了解Rails的真实性令牌

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


1
谢谢,但是我已经知道什么是真实性令牌。检查该客户端/ IP是谁,看起来他们在使用您的网站而不加载您的视图。抱歉,“不加载视图”是什么意思?
Nikita Rybak

1
我的意思是,某个人(可能是垃圾邮件发送者)可能无需通过应用程序的用户界面就可以将数据提交到表单。例如,可以使用curl等命令行程序来执行此操作。
约翰·托普利

约翰说得很对。这意味着他们将采取行动来处理您的表单提交,而无需在您的网站上呈现您的表单。这可能是恶意的(例如发布垃圾评论),也可能表明客户试图直接使用您的Web服务API。您是唯一可以根据您的产品的性质并分析您的要求的人。
温菲尔德

好吧,我误解了温菲尔德的评论。我以为使用浏览器时未将应用程序配置为“加载我的视图”。
Nikita Rybak 2010年

1
我也有另一个想法,这些请求包含一个令牌,但这是无效的。这可能是由于缓存了呈现您的表单的页面或其他可能导致表单过时的版本所致。
温菲尔德

26

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

当使用反向代理(例如nginx)作为HTTPS请求的接收者并将未加密的请求传输到后端(例如Rails应用)时,后端(更具体地说:Rack)需要一些标头,其中包含有关原始客户端请求的更多信息为了能够应用各种处理任务和安全措施。

更多详细信息请参见:https//github.com/rails/rails/issues/22965

TL; 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;
}

哇,我一直在寻找3个小时的解决方案,就这样,谢谢!
evexoio

非常感谢您6个小时的尝试来解决这个问题
Joe Half Face

18

为时已晚,但我找到了解决方案。

定义自己的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>

因此,解决该问题的方法是添加authenticity_token字段或使用rails表单助手,而不是删除,降级或升级rails。


9

如果您做了rake rails:update或最近以其他方式更改了config/initializers/session_store.rb,则可能是浏览器中的旧Cookie的症状。希望这是在dev / test中完成的(对我而言),您只需清除与该域相关的所有浏览器cookie。

如果这是在生产中,并且您进行了更改key,请考虑将其更改回以使用旧的cookie(<-只是推测)。


是! 对我来说,使用空的session_store.rb会导致错误。
lafeber

6

我在使用javascript调用时遇到了这个问题。我只需要将jquery_ujs放入application.js文件即可解决此问题。


是的,我也遇到了这个问题,并在应用程序js中添加了jquery_ujs。有效。
阿比(Abhi)

3

我们遇到了同样的问题,但是注意到这仅适用于使用http://的请求,而不适用于使用https://的请求。原因是secure: truesession_store:

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

通过使用HTTPS〜Everywhere固定:)


我在使用rails s(非SSL)而不是为开发设置的SSL端点时遇到此问题。直到我读到您的评论后,我才意识到自己在做什么。一旦我切换回使用SSL,一切就会重新开始。谢谢!
Karl Wilbur

1
我在开发中遇到了这个问题。而不是secure: true我写的secure: !Rails.env.development?
murb

1

对于Rails 5,最好添加而 protect_from_forgery prepend: true不是跳过verify_authentication_token


5
为什么?您可以添加参考吗?
kwerle


0

我遇到了这个问题,原因是因为我将控制器复制并粘贴到了我的应用程序中。我需要更改ApplicationControllerApplicationController::Base


0

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


0

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


0

我检查了<%= csrf_meta_tags%>是否存在,并且清除浏览器中的cookie对我来说很有用。


0

遵循Chrome Lighthouse建议以加快应用程序加载速度,我已经异步使用了Javascript:

views/layout/application.html.erb

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

这破坏了一切,并为我的远程表单获取了Token错误。删除async: true解决了问题。


0

这个答案更特定于Ruby on Rails,但希望它将对某人有所帮助。

您需要在每个非GET请求中包含CSRF令牌。如果您习惯使用JQuery,Rails jquery-ujs会在其之上构建一个名为helper的帮助程序库,并添加一些隐藏功能。它要做的一件事是在每个ajax请求中自动包括CSRF令牌。看这里

如果您像我一样离开它,可能会发现自己出错。您可以只手动提交令牌,也可以使用其他库来帮助从DOM刮取令牌。有关更多详细信息,请参见这篇文章


-1

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

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

-2

正在安装

gem 'remotipart' 

可以帮忙


3
尽管这可能是答案,但是将答案的必要部分包括在内并解释其原因/工作方式也很有帮助。
罗伊·李

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.