6

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

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

一般来说,这很容易做到。我什至在博客上写了一段时间。但是,我很难弄清楚如何让当前用户向 Web 服务器发出请求,以便我可以记录谁在我的审计跟踪中进行了哪些更改。

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

我读过很多“答案”,说要使用线程存储并将 current_user 放在那里。由于许多其他人不喜欢的原因,我不喜欢这个答案 - 不能保证线程存储是安全的。如果服务器使用同一个线程处理多个请求等,它可能会在多个请求中流血。

所以...鉴于我不是试图从我的模型访问 current_user ,而是从 ActiveSupport::Concern 或 ActiveSupport::Notifications 事件订阅,我有什么好的选择可以知道当前用户是谁?

更新

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

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

4

2 回答 2

3

RailsActionController::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
于 2017-10-03T22:41:55.250 回答
-1

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

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

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

于 2011-08-18T21:07:22.717 回答