4

它应该是这样工作的:我登录到管理面板,转到汽车/新车并填写字段,按创建,我的列表中应该有一辆新车。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

用户控制器: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 导致了这个问题,但最后我解决了这个问题,这不是因为监狱长配置。

4

1 回答 1

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) 中被调用,如果您的应用程序 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 上没有发生。

你的问题是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该剧集将指导您完成设置。

于 2011-12-18T22:43:35.583 回答