我正在寻找一种方法来显示Rails日志中每一行的当前用户。 例如 [约翰多]在 2020-06-07 01:10:33 +0000 开始为 127.0.0.1 获取"/">
一些研究建议使用 rails config.log_tags 设置
(我想出了一个解决方案,但我完全不知道这是否有安全后果(。
我发现了一些想法,涉及通过他们的会话和cookie查找用户ID。这不适用于清除req.env不包含相同的数据。
- http://blog.simontaranto.com/post/2018-05-18-better-rails-logs-current-user-request-context.html/
- 如何在 Rails 中登录user_name?
最终代码
req 是 ActionDispatch::Request 的一个实例,它是在加载网页时创建的。您可以在config.log_tags中使用Proc(通常在config/application.rb或config/environment/.rb中设置(,如下所示:
config.log_tags = [
->(req) { User.current_user_from_request(req) }
]
User.current_user_from_request(请求(是我创建的用于处理抓取用户的方法。这是当前的有效实现:
def self.current_user_from_request(req)
user = req.env.fetch('rack.request.form_hash', nil)&.fetch('session', nil)&.fetch('email', nil)
if user.blank?
Clearance::RackSession.new(Rails.application).call(req.env) unless req.env.key?(:clearance)
user = req.env[:clearance]&.current_user&.email
# This line is specific to my implementation. I identify users by their email, and dont need to know the domain
end
user.split("@").first if user.present?
end
笔记
如果你想知道我是如何得出这个结论的,请继续阅读。
我发现清除具有 Clearance::RackSession 和方法 call(env(从 cookie 中读取以前存在的会话并在每个响应上维护 cookie。
此代码向 req.env 添加了一个 :清除键
Clearance::RackSession.new(Rails.application(.call(req.env(
从这里,查找当前用户很简单:
req.env[:clearance]&.current_user
它返回一个 User 实例(继承自 ApplicationRecord(
提出了几个问题
对每个请求执行此操作会导致堆栈太深错误:
Clearance::RackSession.new(Rails.application(.call(req.env( 除非 req.env.key?(:clearance(
这一直有效,直到我注销并重新登录,在那里它引发了一个ActionController::InvalidAuthenticityToken错误。看起来我正在违反伪造保护。
在引发此错误时检查 req.env,我发现在/sessions/sign_in 上提交的表单哈希包含用户的电子邮件,可在此处访问:
req.env['rack.request.form_hash']
因此,如果我首先尝试访问它(这适用于sign_in和sign_out请求(并回退到上述解决方案(适用于所有其他操作(,我们有一个可行的解决方案:
user = req.env.fetch('rack.request.form_hash', nil(&.fetch('session', nil(&.fetch('email', nil(
有关整个内容,请参阅上面的"最终代码"部分。我还想重申,我不知道这有什么安全影响,或者是否有任何影响。