如何从Rails通知中访问current_user?

时间:2011-06-29 02:37:56

标签: ruby-on-rails-3 security notifications audit-trail

我正在构建一个审计跟踪,需要知道哪个用户当前正在发出请求。我的审计跟踪是使用ActiveSupport :: Notifications构建的,以接收需要审计的偶数。

我想要做的是使用ActiveSupport :: Concern封装逻辑以满足我的审计需求,这样我就可以轻松地将审计添加到我系统中的任何模型中。

一般来说,这很容易做到。我甚至blogged about it a while back。但是,我很难弄清楚如何让当前用户向Web服务器发出请求,以便我可以记录谁在审计跟踪中进行了哪些更改。

我知道有很多关于“如何在我的模型中获得current_user”的问题,但我并不是要求在模型中进行,所以我希望有更好的答案。由于我的审计代码与基础架构相关,我希望有一些方法可以利用当前正在处理的请求,或者其他可以明确告诉我当前登录/发出请求的内容。

我已经阅读了许多说“使用线程存储并将current_user放在那里”的“答案”。我不喜欢这个答案,因为其他人没有这个原因 - 不能保证线程存储是安全的。如果服务器使用相同的线程处理多个请求等,它可能会渗透多个请求。

所以......鉴于我没有尝试从我的模型访问current_user,而是从ActiveSupport :: Concern或ActiveSupport :: Notifications事件订阅中获取,有什么好的选择让我知道当前用户是谁是

更新

我正在使用设计进行身份验证,后端使用Warden。设计通过调用request.env['warden'].authenticate(:scope => :user)来检索current_user(假设我使用“用户”模型进行身份验证)。

我可以通过我的关注或通知订阅访问当前request对象吗?回到我的.NET时代,我本来可以打电话给HttpContext.Current.Request,一切都会好的。 Rails中的等价物是什么?

2 个答案:

答案 0 :(得分:1)

滑轨' ActionController::Instrumentation使用append_info_to_payload明确支持此功能。

ApplicationController添加方法:

def append_info_to_payload(payload)
  super
  payload[:current_user_id] = current_user.try(&:id)
end

现在,当您的观察者被回叫时,信息将在event.payload

ActiveSupport::Notifications.subscribe /process_action.action_controller/ do |*args|
  event = ActiveSupport::Notifications::Event.new(*args)
  current_user_id = event.payload[:current_user_id]
  # do something interesting with current_user_id here
end

答案 1 :(得分:-1)

您已经有了答案,您所做的与人们在模特中访问请求的情况相同。 current_user只是ApplicationController上定义的方法。当您不在控制器或从其继承的其他类中时,您无法访问该方法。

HttpContext.Current.Request<<我敢打赌,这会使用线程存储。我们发现的任何其他解决方案也将是某种程度的线程存储。

从控制器中的请求中提取您需要的内容并将其作为参数传递下来,或者使用线程存储 - 但这无论如何都是本质上的危险。如果你开始使用延迟工作来做通知或什么怎么办?