【问题标题】:rails 3 warden NameError (uncaught throw `warden'):rails 3warden NameError(未捕获的 throw `warden'):
【发布时间】:2011-12-16 22:03:25
【问题描述】:

它应该是这样工作的: 我登录到管理面板,转到汽车/新车并填写字段,按创建,我的列表中应该有一辆新车。 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 中选择汽车名称时,只会出现所选汽车的型号。检查问题(和我的老师一起,我自己不会想到)我们看到当我选择汽车时,一个名为“dynamic_carmodels”的进程正在日志中运行以更新汽车型号列表,此时会话密钥由另一个更改,通常如果更改会话密钥,我登录时启动的会话不再有效,这就是我收到“未经身份验证的错误”的原因。仍然不知道究竟是什么 jquery 导致了这个问题,但最后我解决了这个问题,这不是因为warden 配置。

【问题讨论】:

  • 似乎它依赖于 rails_warden,它应该由 bundler 拾取但尝试一下。
  • 谢谢,我现在正在尝试。我正在与支持人员交谈以尝试您的建议。
  • 如果您正在查看 Warden,我真的建议您使用 Devise,它可以解决很多问题...
  • Warden 很好,只是他没有正确配置。设计需要更多的工作

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


【解决方案1】:

好的,我会非常仔细地向您解释为什么会发生此异常,但我无法为您解决。

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) 中被调用,如果您的应用程序 throws(: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>'

如您所见,我第二次调用了身份验证!我在 catch(:warden) 块之外,因此当我抛出 :warden 时,没有 catch 块来捕捉它,发生异常。

这是发生在你身上的事情,看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 上没有发生。

你的问题是守望者没有正确设置(没有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 该集将指导您完成设置。

【讨论】:

  • 我有 manager.rb 和服务器上的应用程序代码,它的副本在这里github.com/rmagnum2002/zeepauto/blob/master/vendor/bundle/ruby/… 但是回溯代码呢?我应该把它放在哪里?
  • 我的意思是替换warden.authenticate!使用该代码,因此我们可以记录回溯消息。
  • 对不起,你的意思是github.com/rmagnum2002/zeepauto/blob/master/app/controllers/…?典狱长。认证!用回溯代码替换?以前没用过这样的招数,也不知道怎么弄好。
  • 它只是包装了 throws(:warden) 的调用以捕获 NameError 异常,然后使用异常处理程序进行回溯。我在拉取请求上犯了一个错误,删除重复的代码。
  • 你能写一个关于这个解决方案的更详细的教程吗?我真的不知道(以及支持人员)把这段代码放在哪里以及它应该是什么样子,如果你愿意把它拿出来的话。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-02
  • 2014-10-29
  • 1970-01-01
  • 2013-10-12
  • 1970-01-01
  • 1970-01-01
  • 2010-12-01
相关资源
最近更新 更多