【问题标题】:nil.[] in request_forgery_protection when trying to render a form in rails 3尝试在 Rails 3 中呈现表单时, request_forgery_protection 中的 nil.[]
【发布时间】:2011-10-18 15:11:31
【问题描述】:

每当我尝试向其添加 form_tag 时,Rails 都会在页面上引发 NoMethodError,并提供以下错误输出和堆栈跟踪:

You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.[]

ruby/1.9.1/gems/actionpack-3.0.5/lib/action_controller/metal/request_forgery_protection.rb:114:in `form_authenticity_token'
ruby/1.9.1/gems/actionpack-3.0.5/lib/abstract_controller/helpers.rb:55:in `form_authenticity_token'
ruby/1.9.1/gems/actionpack-3.0.5/lib/action_view/helpers/form_tag_helper.rb:582:in `token_tag'
ruby/1.9.1/gems/actionpack-3.0.5/lib/action_view/helpers/form_tag_helper.rb:555:in `extra_tags_for_form'
ruby/1.9.1/gems/actionpack-3.0.5/lib/action_view/helpers/form_tag_helper.rb:566:in `form_tag_html'
ruby/1.9.1/gems/actionpack-3.0.5/lib/action_view/helpers/form_tag_helper.rb:573:in `form_tag_in_block'
ruby/1.9.1/gems/actionpack-3.0.5/lib/action_view/helpers/form_tag_helper.rb:52:in `form_tag'
app/views/teams/new.html.erb:1:in `_app_views_teams_new_html_erb__114968057028112192_2181733580__2538292988913059192'

堆栈跟踪还有更多内容,但相关部分是它是从被调用的 form_tag 触发的,并且会导致 request_forgery_protection。

当我从页面中删除 form_tag 时,错误仍然存​​在,但现在它被触发 在我的应用程序布局中。

本例中的trace也指向控制器中request_forgery_protection方法中的同一行

ruby/1.9.1/gems/actionpack-3.0.5/lib/action_controller/metal/request_forgery_protection.rb:114:in `form_authenticity_token'
ruby/1.9.1/gems/actionpack-3.0.5/lib/abstract_controller/helpers.rb:55:in `form_authenticity_token'
ruby/1.9.1/gems/actionpack-3.0.5/lib/action_view/helpers/csrf_helper.rb:9:in `csrf_meta_tag'
app/views/layouts/application.html.erb:5:in `_app_views_layouts_application_html_erb___1820392644171111615_2183801660__2538292988913059192'

我已经尝试在我的 ApplicationController 中注释掉“protect_from_forgery”,但这没有任何作用。而且我还尝试注释掉 csrf_meta_tag,当我将其注释掉并删除 form_tag 时,可以渲染动作。

为了调试这个,我试图让我的视图成为最基本的:

<div>
<h1>This is a Header</h1>

<%= form_tag do %>
  Form contents
<% end %>
</div>

而我的控制器如下:

class TeamsController < ApplicationController
  before_filter :authenticate_user!
  check_authorization
  load_and_authorize_resource

  def new
    @team = Team.new
  end
end

我尝试使用的相关 gem 是:Devise、Cancan 和 Rails 3.0.5

编辑:我的会话转储如下 -

_csrf_token: "iZRWhye/WBrzjWbKreJVIRpfTbfpbSaaJu3fMiW3wEg="
flash: {:notice=>"Signed in successfully."}
session_id: "85fc7d152a17ca884f5b299f4cde926b"
warden.user.user.key: ["User", [1], "$2a$10$KC66DL1T.71ERw4d4VHVq."]
warden.user.user.session: {"last_request_at"=>2011-08-02 22:03:57 UTC}

【问题讨论】:

  • 嗯根据回溯,看起来会话对象为零。要查看是否是这种情况,请从您的视图中删除 form_tag,然后添加 &lt;%= session.inspect %&gt;。如果它为零,那么这就是原因(至少在表面上);但我不确定为什么 session 会为零。
  • 我做了更多的挖掘并查看了 request_forgery_protection.rb 中的form_authenticity_token 方法;它打电话给session[:_csrf_token] ||= ActiveSupport::SecureRandom.base64(32),它似乎从该行提出了一个 nil 数组。由于我的 _csrf_token 具有价值,我真的不知道它为什么要这样做。
  • 我看到了同一行。错误消息说它正在尝试调用 nil.[] 。我在该代码行上看到的唯一括号是在会话对象上调用的,这就是为什么我问你尝试显示会话的原因,我怀疑它是 nil。
  • /config/initializers/session_store.rb 中设置的会话存储是什么?
  • 所以@Kelvin 怀疑 会为零。

标签: ruby-on-rails session-cookies csrf


【解决方案1】:

把它放在你的视图中并粘贴输出:

<pre>
<%= method(:session)  %>
<%= instance_variable_get(:@controller).method(:session) %>
<%= instance_variable_get(:@controller).instance_variable_get(:@_request).session.inspect %>
</pre>

如果您的控制器名为 HomeController,您将看到如下内容:

#<Method: #<Class:0x1cc12fc>(ActionView::Base)#session>
#<Method: HomeController(ActionController::Metal)#session>
{"_csrf_token"=>"R4KKC1hDCzY5hUcIks1xIUonEpywlhjKqjJS7J1gCOk=", "session_id"=>"886b4f181bdc955250424858f45887ad"}

可能在委托链中的某个点重新定义会话方法。

【讨论】:

  • 显然在 RegistrationsController 中声明了一个名为 session 的方法,它是一个空方法。删除它消除了问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多