如何从 Rails 通知访问 current_user?

Posted

技术标签:

【中文标题】如何从 Rails 通知访问 current_user?【英文标题】:How to access current_user from a Rails Notification? 【发布时间】:2011-06-29 02:37:55 【问题描述】:

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

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

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

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

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

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

更新

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

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

【问题讨论】:

感谢链接修复。 :) 正要这样做,看到你已经处理好了! 您找到解决方案了吗?如果你这样做了,请写下来。谢谢。 【参考方案1】:

Rails 的 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

【讨论】:

感谢您提供此信息,这仍然是最好的方法吗? 它似乎仍然活跃api.rubyonrails.org/classes/ActionController/… 我不清楚是否只有来自 action_controller 的通知才会有这个。我正在使用机架攻击并尝试访问 current_user 进行日志记录【参考方案2】:

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

HttpContext.Current.Request

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

【讨论】:

事实证明这是可能的,使用 rails 显式功能,不需要线程本地存储,使用append_info_to_payload

以上是关于如何从 Rails 通知访问 current_user?的主要内容,如果未能解决你的问题,请参考以下文章

Rails 5,动作电缆和 current_user

如何在 ActionCable rails-5-api 应用程序中获取 current_user?

如何仅更新 rails 6 中 current_user 的嵌套表单属性?

Ruby on Rails - 如何在 Rails 方法中使用 HTML 坐标?

<%= current_user.role %> 在 Rails 4 中计算结果为空

Rails - 如何查找单个记录(用户名)在主页中向任何访问者显示它