简体   繁体   English

ActionController::InvalidAuthenticityToken

[英]ActionController::InvalidAuthenticityToken

Below is an error, caused by a form in my Rails application:下面是一个错误,由我的 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):

This happens for every non- get request and, as you see, authenticity_token is there.对于每个非get请求都会发生这种情况,如您所见, authenticity_token就在那里。

I had the same issue but with pages which were page cached.我有同样的问题,但页面缓存了页面。 Pages got buffered with a stale authenticity token and all actions using the methods post/put/delete where recognized as forgery attempts.页面被一个陈旧的真实性令牌缓冲,所有使用 post/put/delete 方法的操作都被识别为伪造尝试。 Error (422 Unprocessable Entity) was returned to the user.错误 (422 Unprocessable Entity) 被返回给用户。

The solution for Rails 3: Rails 3 的解决方案:
Add:添加:

 skip_before_filter :verify_authenticity_token  

or as "sagivo" pointed out in Rails 4 add:或者如 Rails 4 中指出的“sagivo”添加:

 skip_before_action :verify_authenticity_token

On pages which do caching.在进行缓存的页面上。

As @toobulkeh commented this is not a vulnerability on :index , :show actions, but beware using this on :put , :post actions.正如@toobulkeh 评论的那样,这不是:index:show动作的漏洞,但要小心在:put:post动作上使用它。

For example:例如:

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

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

Note added by barlop- Rails 4.2 deprecated skip_before_filter in favour of skip_before_action https://guides.rubyonrails.org/4_2_release_notes.html "The *_filter family of methods have been removed from the documentation. Their usage is discouraged in favor of the *_action family of methods" barlop 添加的注释-Rails 4.2 已弃用skip_before_filter 以支持skip_before_action https://guides.rubyonrails.org/4_2_release_notes.html “*_filter 系列方法已从文档中删除。不鼓励使用 *_action方法族”

For Rails 6 (as "collimarco" pointed out) you can use skip_forgery_protection and that it is safe to use it for a REST API that doesn't use session data.对于Rails 6 (如“collimarco”所指出的),您可以使用skip_forgery_protection并且将其用于不使用会话数据的 REST API 是安全的。

For me the cause of this issue under Rails 4 was a missing,对我来说,Rails 4 下这个问题的原因是缺失的,

<%= csrf_meta_tags %>

Line in my main application layout.行在我的主要应用程序布局中。 I had accidently deleted it when I rewrote my layout.我在重写布局时不小心删除了它。

If this isn't in the main layout you will need it in any page that you want a CSRF token on.如果这不在主布局中,您将需要在您想要 CSRF 令牌的任何页面中使用它。

There are several causes for this error, (relating to Rails 4).此错误有多种原因(与 Rails 4 相关)。

1. Check <%= csrf_meta_tags %> present in page layout 1. 检查页面布局中存在的<%= csrf_meta_tags %>

2. check authenticity token is being sent with AJAX calls if using form_for helper with remote: true option.If not you can include the line <%= hidden_field_tag :authenticity_token, form_authenticity_token %> withing the form block. 2. 如果使用form_for helper 和remote: true请检查真实性令牌是否通过 AJAX 调用发送。如果不是,您可以在表单块中包含行<%= hidden_field_tag :authenticity_token, form_authenticity_token %>

3. If request is being sent from cached page, use fragment caching to exclude part of page that sends request eg button_to etc. otherwise token will be stale/invalid. 3. 如果请求是从缓存页面发送的,使用片段缓存来排除发送请求的页面部分,例如button_to等。否则令牌将失效/无效。

I would be reluctant to nullify csrf protection...我不愿意取消csrf保护......

只需在表单中添加authenticity_token为我修复它。

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>

ActionController::InvalidAuthenticityToken can also be caused by a misconfigured reverse proxy. ActionController::InvalidAuthenticityToken也可能由错误配置的反向代理引起。 This is the case if in the stack trace, you get a line looking like Request origin does not match request base_url .如果在堆栈跟踪中,您会看到一行看起来像是Request origin does not match request base_url

When using a reverse proxy (such as nginx) as receiver for HTTPS request and transmitting the request unencrypted to the backend (such as the Rails app), the backend (more specifically: Rack) expects some headers with more information about the original client request in order to be able to apply various processing tasks and security measures.当使用反向代理(例如 nginx)作为 HTTPS 请求的接收者并将未加密的请求传输到后端(例如 Rails 应用程序)时,后端(更具体地说:Rack)需要一些标头,其中包含有关原始客户端请求的更多信息以便能够应用各种处理任务和安全措施。

More details are available here: https://github.com/rails/rails/issues/22965 .此处提供更多详细信息: https : //github.com/rails/rails/issues/22965

TL;DR: the solution is to add some headers: 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;
}

The authenticity token is a random value generated in your view to prove a request is submitted from a form on your site, not somewhere else.真实性令牌是在您的视图中生成的随机值,用于证明请求是从您网站上的表单提交的,而不是其他地方。 This protects against CSRF attacks:这可以防止 CSRF 攻击:

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

Check to see who that client/IP is, it looks like they are using your site without loading your views.检查该客户端/IP 是谁,看起来他们正在使用您的站点而没有加载您的视图。

If you need to debug further, this question is a good place to start: Understanding the Rails Authenticity Token如果你需要进一步调试,这个问题是一个很好的起点: Understanding the Rails Authenticity Token

Edited to explain: It means they are calling the action to process your form submit without ever rendering your form on your website.编辑解释:这意味着他们正在调用处理您的表单提交的操作,而无需在您的网站上呈现您的表单。 This could be malicious (say posting spam comments) or it could indicate a customer trying to use your web service API directly.这可能是恶意的(比如发布垃圾评论),也可能表明客户试图直接使用您的 Web 服务 API。 You're the only one who can answer that by the nature of your product and analyzing your requests.您是唯一可以通过产品的性质和分析您的要求来回答这个问题的人。

too late to answer but I found the solution.来不及回答,但我找到了解决方案。

When you define you own html form then you miss authentication token string that should be sent to controller for security reasons.当您定义自己的 html 表单时,您会错过出于安全原因应发送到控制器的身份验证令牌字符串。 But when you use rails form helper to generate a form you get something like following但是当您使用 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>

So the solution to the problem is either to add authenticity_token field or use rails form helpers rather then removing , downgrading or upgrading rails.所以问题的解决方案是添加authenticity_token 字段或使用rails 表单助手,而不是删除、降级或升级rails。

If you have done a rake rails:update or otherwise recently changed your config/initializers/session_store.rb , this may be a symptom of old cookies in the browser.如果您执行了rake rails:update或最近更改了config/initializers/session_store.rb ,这可能是浏览器中旧 cookie 的症状。 Hopefully this is done in dev/test (it was for me), and you can just clear all browser cookies related to the domain in question.希望这是在开发/测试中完成的(它是给我的),并且您可以清除与相关域相关的所有浏览器 cookie。

If this is in production, and you changed key , consider changing it back to use the old cookies (<- just speculation).如果这是在生产中,并且您更改了key ,请考虑将其改回使用旧的 cookie (<- 只是推测)。

I had this issue with javascript calls.我在 javascript 调用中遇到了这个问题。 I fixed that with just requiring jquery_ujs into application.js file.我只需要 jquery_ujs 到 application.js 文件中就解决了这个问题。

We had the same problem, but noticed that it was only for requests using http:// and not with https://.我们遇到了同样的问题,但注意到它仅适用于使用 http:// 而不是 https:// 的请求。 The cause was secure: true for session_store:原因是secure: true对于 session_store 是secure: true

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

Fixed by using HTTPS ~everywhere :)通过使用 HTTPS ~everywhere 修复:)

Add添加

//= require rails-ujs 

in

\app\assets\javascripts\application.js

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

I had this problem and the reason was because I copied and pasted a controller into my app.我遇到了这个问题,原因是我将控制器复制并粘贴到我的应用程序中。 I needed to change ApplicationController to ApplicationController::Base我需要将ApplicationController更改为ApplicationController::Base

I had the same issue on localhost.我在本地主机上遇到了同样的问题。 I have changed the domain for the app, but in URLs and hosts file there was still the old domain.我已经更改了应用程序的域,但在 URL 和主机文件中仍然存在旧域。 Updated my browser bookmarks and hosts file to use new domain and now everything works fine.更新了我的浏览器书签和主机文件以使用新域,现在一切正常。

Maybe you have your NGINX setup for HTTPS but your certificates are invalid?也许您已为 HTTPS 设置了 NGINX,但您的证书无效? I've had a similar problem in the past and redirecting from http to https solved the problem我过去遇到过类似的问题,从 http 重定向到 https 解决了这个问题

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

Following Chrome Lighthouse recommendations for a faster application load, I have asynced my Javascript:按照 Chrome Lighthouse 对更快应用程序加载的建议,我已经异步了我的 Javascript:

views/layout/application.html.erb

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

This broke everything and got that Token error for my remote forms.这打破了一切,并为我的远程表单获取了 Token 错误。 Removing async: true fixed the problem.删除async: true解决了问题。

This answer is much more specific to Ruby on Rails, but hopefully it will help someone.这个答案更具体地针对 Ruby on Rails,但希望它会对某人有所帮助。

You need to include the CSRF token with every non-GET request.您需要在每个非 GET 请求中包含 CSRF 令牌。 If you're used to using JQuery, Rails has a helper library called jquery-ujs that builds on top of it and adds some hidden functionality.如果您习惯使用 JQuery,Rails 有一个名为jquery-ujs的辅助库,它构建在它之上并添加了一些隐藏功能。 One of the things it does is automatically includes the CSRF token in every ajax request.它所做的一件事是在每个ajax请求中自动包含 CSRF 令牌。 See here . 见这里

If you switch away from it like I did you might find yourself with an error.如果你像我一样离开它,你可能会发现自己有错误。 You can just submit the token manually or use another library to help scrape the token from the DOM.您可以手动提交令牌或使用另一个库来帮助从 DOM 中抓取令牌。 See this post for more detail.有关更多详细信息,请参阅此帖子

For Development environment, I tried many of these attempts to fix this issue, in Rails 6. None of them helped.对于开发环境,我在 Rails 6 中尝试了许多这些尝试来解决这个问题。它们都没有帮助。 So if none of these suggestions worked for you, try below.因此,如果这些建议都不适合您,请尝试以下方法。

The only solution I found was to add a txt file into your /tmp folder.我找到的唯一解决方案是将 txt 文件添加到您的 /tmp 文件夹中。

In your app's root directory, either run:在您的应用程序的根目录中,运行:

touch tmp/caching-dev.txt

Or manually create a file by that name in your /tmp folder.或者在您的 /tmp 文件夹中手动创建一个具有该名称的文件。 Since this fixed it for me, I assume the root of the issue is a caching conflict.由于这为我修复了它,我认为问题的根源是缓存冲突。

Running rails dev:cache in my console fixed this for me!在我的控制台中运行rails dev:cache为我解决了这个问题! (Rails 6) (导轨 6)

I think it might be something to do with Turbolinks, but CSRF only seems to work when local caching is enabled .我认为这可能与 Turbolinks 有关,但 CSRF 似乎仅在启用本地缓存时才起作用。

This happened to me when carrying out manual tests of the sign up process of my application (signing up/in with multiple users).这发生在我对我的应用程序的注册过程(注册/与多个用户注册)进行手动测试时。

A very simple and pragmatic solution may be to do what I did, and use a different browser (or incognito if using chrome).一个非常简单实用的解决方案可能是做我所做的,并使用不同的浏览器(如果使用 chrome,则使用隐身浏览器)。

This was a much better solution in my case than disabling security features!!这是在我的情况下,更好的解决方案比禁用安全功能!

This happened to me when upgrading from Rails 4.0 to 4.2.这发生在我从 Rails 4.0 升级到 4.2 时。

The 4.2 implementation of verified_request? 4.2 Verified_request 的实现verified_request? looks at request.headers['X-CSRF-Token'] , whereas the header my 4.0 app had been getting was X-XSRF-TOKEN .查看request.headers['X-CSRF-Token'] ,而我的 4.0 应用程序获得的标头是X-XSRF-TOKEN A quick fix in my ApplicationController was to add the function:我的 ApplicationController 中的一个快速修复是添加函数:

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

I experienced a similar error in Rails 6. Having tried the solutions above, I did a form review and saw that I had used a <button>.....</button> HTML tag in my form instead of submitting through Rails我在 Rails 6 中遇到了类似的错误。尝试了上述解决方案后,我进行了表单审查,发现我在表单中使用了<button>.....</button> HTML 标记,而不是通过 Rails 提交

<%= form.submit %>
form helper. 表格助手。 Changing to the form helper resolved the issue. 更改为表单助手解决了该问题。

Installing安装

gem 'remotipart' 

can help可以帮助

In rails 5, we need to add 2 lines of code在rails 5中,我们需要添加2行代码

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

Problem solved by downgrading to 2.3.5 from 2.3.8.通过从 2.3.8 降级到 2.3.5 解决了问题。 (as well as infamous 'You are being redirected.' issue) (以及臭名昭著的“您正在被重定向。”问题)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM