Ruby on rails Rails 5:如何更正已完成的422不可处理实体错误?

Ruby on rails Rails 5:如何更正已完成的422不可处理实体错误?,ruby-on-rails,authentication,login,csrf,csrf-protection,Ruby On Rails,Authentication,Login,Csrf,Csrf Protection,我在Heroku中有一个Rails 5应用程序,它使用基于Michael Hartl的Ruby on Rails教程中的逻辑的会话控制器进行登录/注销。从Rails 3开始,我已经做了几年类似的逻辑。我的应用程序在本地主机上工作,生产状态在我的服务器和Heroku上使用Passenger。正在执行相同的代码。几天前,当我尝试在服务器上登录到应用程序的生产版本时,我开始出现以下错误。但是,我仍然能够在localhost/development和Heroku上登录到我的应用程序 I, [2017-0

我在Heroku中有一个Rails 5应用程序,它使用基于Michael Hartl的Ruby on Rails教程中的逻辑的会话控制器进行登录/注销。从Rails 3开始,我已经做了几年类似的逻辑。我的应用程序在本地主机上工作,生产状态在我的服务器和Heroku上使用Passenger。正在执行相同的代码。几天前,当我尝试在服务器上登录到应用程序的生产版本时,我开始出现以下错误。但是,我仍然能够在localhost/development和Heroku上登录到我的应用程序

I, [2017-04-22T20:15:50.242323 #65501]  INFO -- : [40a379f9-27c2-4923-a9ce-f310f96dbc4c] Started POST "/sessions" for 127.0.0.1 at 2017-04-22 20:15:50 -0500
I, [2017-04-22T20:15:50.243524 #65501]  INFO -- : [40a379f9-27c2-4923-a9ce-f310f96dbc4c] Processing by SessionsController#create as HTML
I, [2017-04-22T20:15:50.243945 #65501]  INFO -- : [40a379f9-27c2-4923-a9ce-f310f96dbc4c]   Parameters: {"utf8"=>"✓", "authenticity_token"=>"RsEqEfiDw82E2YI17SVkkUcxhiqtUw75nC1i9GJmIYZlwjg6o0mXiHehCHP627iTOjyQoPA+mrmi+Bh99BxICQ==", "session"=>{"email_user"=>"pamela", "password"=>"[FILTERED]"}, "commit"=>"Login"}
W, [2017-04-22T20:15:50.245161 #65501]  WARN -- : [40a379f9-27c2-4923-a9ce-f310f96dbc4c] Can't verify CSRF token authenticity.
I, [2017-04-22T20:15:50.246050 #65501]  INFO -- : [40a379f9-27c2-4923-a9ce-f310f96dbc4c] Completed 422 Unprocessable Entity in 2ms (ActiveRecord: 0.0ms)
F, [2017-04-22T20:15:50.248110 #65501] FATAL -- : [40a379f9-27c2-4923-a9ce-f310f96dbc4c]   
F, [2017-04-22T20:15:50.248546 #65501] FATAL -- : [40a379f9-27c2-4923-a9ce-f310f96dbc4c] ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
F, [2017-04-22T20:15:50.248894 #65501] FATAL -- : [40a379f9-27c2-4923-a9ce-f310f96dbc4c]   
F, [2017-04-22T20:15:50.249263 #65501] FATAL -- : [40a379f9-27c2-4923-a9ce-f310f96dbc4c] actionpack (5.0.2) lib/action_controller/metal/request_forgery_protection.rb:195:in `handle_unverified_request'
[40a379f9-27c2-4923-a9ce-f310f96dbc4c] actionpack (5.0.2) lib/action_controller/metal/request_forgery_protection.rb:223:in `handle_unverified_request'
[40a379f9-27c2-4923-a9ce-f310f96dbc4c] actionpack (5.0.2) lib/action_controller/metal/request_forgery_protection.rb:218:in `verify_authenticity_token'
应用程序\u控制器

protect_from_forgery with: :exception
include SessionsHelper
从本地主机在我能够成功登录的同一台计算机上登录:

Started POST "/sessions" for ::1 at 2017-04-22 22:26:23 -0500
Processing by SessionsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"zhkoMofyRdPcwQ7v2GOYltlRv2PJM8duzbuxJsa5dAy0je/yj1CRedQM/H1Zku2ukQbbG7YF6OZd4ootV0qolA==", "session"=>{"email_user"=>"myuserid", "password"=>"[FILTERED]"}, "remember_me"=>"1", "commit"=>"Login"}
  [1m[36mUser Load (74.2ms)[0m  [1m[34mSELECT  "users".* FROM "users" WHERE "users"."email" = $1 LIMIT $2[0m  [["email", "myuserid"], ["LIMIT", 1]]
  [1m[36mUser Load (0.8ms)[0m  [1m[34mSELECT  "users".* FROM "users" WHERE "users"."username" = $1 LIMIT $2[0m  [["username", "myuserid"], ["LIMIT", 1]]
  [1m[35m (0.2ms)[0m  [1m[35mBEGIN[0m
  [1m[35mSQL (22.6ms)[0m  [1m[33mUPDATE "users" SET "remember_token" = $1, "updated_at" = $2 WHERE "users"."id" = $3[0m  [["remember_token", "75f5152d815e24e6ce7709cc93f34265ad9161be"], ["updated_at", 2017-04-23 03:26:23 UTC], ["id", 3]]
  [1m[35m (26.4ms)[0m  [1m[35mCOMMIT[0m
Redirected to http://localhost:3000/
Completed 302 Found in 229ms (ActiveRecord: 124.5ms)


Started GET "/" for ::1 at 2017-04-22 22:26:23 -0500
Processing by PagesController#home as HTML
  [1m[36mUser Load (7.4ms)[0m  [1m[34mSELECT  "users".* FROM "users" WHERE "users"."remember_token" = $1 LIMIT $2[0m  [["remember_token", "75f5152d815e24e6ce7709cc93f34265ad9161be"], ["LIMIT", 1]]
  Rendering pages/home.html.erb within layouts/application
  Rendered pages/home.html.erb within layouts/application (1.1ms)
  Rendered layouts/_meta_data.erb (2.3ms)
  Rendered layouts/_shim.html.erb (0.4ms)
  Rendered layouts/_header.html.erb (1.1ms)
  Rendered layouts/_systemmessage.html.erb (0.5ms)
  Rendered layouts/_footer.html.erb (1.0ms)
Completed 200 OK in 270ms (Views: 236.8ms | ActiveRecord: 7.4ms)
我有搜索解决方案,几乎所有的解决方案都说要关闭它,我不想这样做,特别是考虑到这是一个数据库维护应用程序。我能看到的三次代码执行之间的唯一区别是表中membere_token的值,因为每个版本都使用不同的数据库。我尝试将数据库上的memory_token字段设置为null,但仍然出现错误。我没有更改任何与登录/注销过程相关的内容,所以我真的很困惑。我将克隆我在Heroku中拥有的,然后再试一次

这是近六年Rails软件开发中我第一次看到这个错误。我意识到我很可能会受到攻击,但我不知道如何调试这个错误。在Heroku和localhost中也可以使用相同的代码

更新:我查看了服务器上生产应用程序的页面源代码。这是在我尝试登录并出现错误之前标题的样子。对于my localhost版本和Heroku版本,下面的两条语句会在登录后出现

<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="JoPFlDzY0SYSpOSq0dXgafSICgZ9qXJz/x4tX31owZPh3cu7fNR553iGPn5c+RnZVOuxiEolnoOin0Rkoay4Ag==" />

有两个令牌需要验证,
表单令牌
csrf令牌
。任何一个令牌失败,都将抛出
InvalidAuthenticityToken
异常

在生产部署目录下,运行
bundle show rails
,找到确切的
rails
目录,然后将日志添加到相关的rails代码中,查找详细原因

以这种方式添加日志,
logger.warn“无法验证CSRF令牌的真实性。”
,这是rails输出日志的方式

actionpack/lib/action\u controller/metal/request\u forgery\u protection.rb
文件中,查找为什么任何真实性令牌有效?首先失败

并检查此问题,更改为
users\u path
,而不是
users\u url

照顾好这个,,

对于Rails 5,请注意,protect_from_fagery不再是before_action链的前缀,因此如果您在protect_from_fagery之前设置了authenticate_user,您的请求将导致“无法验证CSRF令牌的真实性”。要解决此问题,请更改调用它们的顺序,或者使用protect_from_fagery prepend:true。

根据rails日志,您也不能在本地主机上登录。这是一个CSRF问题,与
记住\u令牌
无关。日志来自获取错误的程序。我正在同一台计算机上的本地主机上成功登录。这就是我完全不知所措的原因。我怎么可能只在生产中出现csrf问题,而在同一台机器上没有本地主机?我如何调试csrf错误而不毫无例外地关闭伪造?如果日志来自您的生产机器,为什么ip是127.0.0.1,那么您可以通过curl伪造post请求?在您自己的制作网站中,如果您可以登录,那么您可能会遇到攻击。如果你不能登录,那就是一个逻辑错误。我认为您应该向生产站点添加更多日志,以显示http头,检查它是否有key
X-CSRF-Token
。我的服务器上有一个指向不同域的应用程序的“生产”版本。我发布的日志来自我的服务器上的应用程序的生产版本,在那里我得到了错误。我刚刚添加了在localhost中成功登录应用程序时的日志语句。因此,在我的应用程序上的localhost登录可以正常工作,但在我的服务器上的生产应用程序上的登录不能正常工作。我现在将日志级别设置为:debug。我将找出如何在我的rails应用程序中获得更详细的日志,希望包括CSRF令牌并发布我的结果。谢谢我需要有关如何添加该日志以及在何处添加日志的帮助。非常感谢你的帮助。我只是搜索了一下,但没有找到任何相关说明。只需找到部署到的代码目录,然后运行
bundle show rails
,找到它的
rails
目录,然后将代码添加到与rails相关的文件
actionpack/lib/action\u controller/metal/request\u forgery\u protection.rb
,这就是异常抛出的地方。日志可以像“logger.warn”一样添加,但不能验证CSRF令牌的真实性。只需监视rails是如何做到的。我无法直接访问rails文件,因为我使用的是Ruby版本管理器(RVM)安装Ruby和Rails。我已经在lib/generators中为迁移和模型创建了自定义生成器。我想知道我是否可以做类似的事情来覆盖类InvalidAuthenticityToken(在第195行中提出)。如果可能的话,我需要知道我的文件的名称和放置位置,以便日志记录器可以找到它。我已更新了我的问题,尝试创建这样的文件。我尝试了不同的方法,但都不起作用。我决定重新开始并克隆应用程序的Heroku版本。我不再收到错误。不确定是什么原因导致了错误CSRF错误,但至少我有Heroku版本可以作为我服务器上的新起点。非常感谢@seaify!我说得太早了。几分钟后,我又出现了错误。看起来我可能必须关闭CSRF或其他极端措施才能修复此问题,除非我能够以某种方式覆盖类InvalidAuthentityToken和see是什么导致了这个问题。我会作为sepa问这个问题
require 'action_controller/metal/request_forgery_protection'

class XxxLogger < ActionPack::ActionController::RequestForgeryProtection
  source_root File.join(File.dirname(ActionPack::ActionController::RequestForgeryProtection.instance_method(:handle_unverified_request).source_location.first), "templates")

  class InvalidAuthenticityToken < ActionControllerError #:nodoc:
    logger.warn "Can't verify CSRF token authenticity
  end

end