rails 3 warden NameError(uncaught throw`warden'):

时间:2011-12-16 22:03:26

标签: ruby-on-rails ruby-on-rails-3 warden

这是它应该如何工作: 我登录管理面板,转到cars / new并填写字段,按下创建,我的列表中应该有一辆新车。 www.autozeep.com

事情是,在我按下“创建”按钮创建新车之前一切正常,服务器日志显示:

NameError (uncaught throw `warden'):
  app/controllers/application_controller.rb:9:in `login_required'
  app/middleware/flash_session_cookie_middleware.rb:17:in `call'

在开发模式下,这工作正常,在生产模式的服务器上它不是,它是相同的代码,没有任何改变。 更多服务器日志:http://pastie.org/3028350

application_controller

class ApplicationController < ActionController::Base
    protect_from_forgery

  # filter

  def login_required
    return true if authenticated?
    warden.authenticate!
  end

users_controller:http://pastie.org/3028586

我可以编辑汽车,它工作正常,所以来自cars_controller的更新和编辑功能都可以,我检查了新的并从cars_controller创建函数但我无法解决任何会让我知道发生了什么的事情。 Cars_controller:http://pastie.org/3028452

请帮助,我已经运行了这个应用程序,等待这个问题的客户端只能解决。非常感谢你们。

修改

NameError in CarsController#create

uncaught throw `warden'

Rails.root: /u/apps/zeepauto/releases/20111123173432
Application Trace | Framework Trace | Full Trace

app/controllers/application_controller.rb:9:in `login_required'
app/middleware/flash_session_cookie_middleware.rb:17:in `call'

ENV DUMP
...
....
rack.url_scheme: "http"
rack.version: [1, 0]
warden: Warden::Proxy:-621456458 @config={:default_strategies=>{:_all=>[:database]}, :failure_app=>UsersController, :default_scope=>:default, :scope_defaults=>{}, :intercept_401=>true}
warden.options: {:attempted_path=>"/cars", :action=>"unauthenticated"}

我只有在添加新车时才能收到此错误,我可以编辑汽车,新闻,联系人。除汽车外的一切。

问题已解决

这个问题是由一些jquery库引起的,我在这种形式下使用dynamic_form,所以当我在下一个select_box中选择car name时,只显示所选汽车的模型。检查问题(我的老师,我自己也不会想到)我们看到当我选择汽车时,日志中会运行一个名为“dynamic_carmodels”的进程来更新carmodels列表,此时还会显示会话密钥由另一个更改,通常如果会话密钥更改,我登录时启动的会话不再有效,这就是我得到“未经身份验证的错误”的原因。仍然不知道jquery究竟是什么导致了这个问题,但最后我得到了解决,这不是因为监狱长的配置。

1 个答案:

答案 0 :(得分:10)

好的我会向你解释为什么这个例外情况会非常小心,但我无法为你解决。

Warden使用catch(:warden)块来保护你的应用程序,你可以在:

中看到这一点
# Invoke the application guarding for throw :warden.
# If this is downstream from another warden instance, don't do anything.
# :api: private
def call(env) # :nodoc:
  return @app.call(env) if env['warden'] && env['warden'].manager != self

  env['warden'] = Proxy.new(env, self)
  result = catch(:warden) do
      @app.call(env)
  end

您的应用程序在@ app.call(env)中被调用,如果您的应用程序抛出(:warden),它就会被捕获。这就是throw,catch的工作原理,这是一个例子:

def authenticate!()
  throw :warden
end

catch(:warden) do
  puts "Calling authenticate!" 
  authenticate!() 
end

puts "Succesfully called authenticate!"
#outside of catch(:) guard
authenticate!()
puts "this never gets executed"

如果我执行此操作,它将执行:

 ruby exc.rb 
 Calling authenticate!
 Succesfully called authenticate!
 exc.rb:2:in `throw': uncaught throw :warden (ArgumentError)
    from exc.rb:2:in `initialize!'
    from exc.rb:12:in `<main>'

如您所见,我第二次打电话进行身份验证!我在捕获(:warden)区域之外,因此当我抛出时:看守没有捕获阻止它,异常发生。

这就是发生在你身上的事,请看warden#authenticate!

def authenticate!(*args)
   user, opts = _perform_authentication(*args)
   throw(:warden, opts) unless user
   user
end

看看throw(:warden,opts)?如果该throw在catch(:warden)块之外,则引发异常。 Warden应该在catch区域保护你的整个应用程序,这样你就可以随时抛出:warden。但由于某些原因,zeepauto上没有发生这种情况。

你的问题是没有正确设置warden(没有config/initializers/warden.rb)和call (env)所以你的catch(:warden)守卫从未设置过。

你的答案在这里:https://github.com/hassox/warden/wiki/Setup

只需自己完成设置即可。你可以随时抛出一个:warden来测试你的开发环境。只需编写一个测试:

it "warden should catch the throw :warden at any point" do
  throw(:warden)
end

如果您希望更快地获得此功能,只需在railscasts.com中获取专业版帐户并观看:http://railscasts.com/episodes/305-authentication-with-warden该剧集将指导您完成设置。