在 Rails 日志中显示用户 id/name,许可 gem
Show user id/name in Rails log with Clearance gem
我正在寻找一种方法来在 Rails 日志中的每一行显示当前用户。例如。
[johndoe] 于 2020 年 6 月 7 日开始为 127.0.0.1 获取“/”01:10:33 +0000
一些研究建议使用 rails config.log_tags 设置
(我想出了一个解决方案,但我完全不知道这是否会带来安全后果)。
我发现了一些想法,涉及通过会话和 cookie 查找用户 ID。这对清关无效 req.env 不包含相同的数据。
- http://blog.simontaranto.com/post/2018-05-18-better-rails-logs-current-user-request-context.html/
- How to log user_name in Rails?
最终代码
req 是 ActionDispatch::Request 的实例,它是在您加载网页时创建的。您可以在 config.log_tags 中使用 Proc(通常在 config/application.rb 或 config/environments/.rb 中设置),如下所示:
config.log_tags = [
->(req) { User.current_user_from_request(req) }
]
User.current_user_from_request(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 和方法调用(env) 从 cookie 中读取以前存在的会话并在每次响应时维护 cookie。
此代码为 req.env 添加了一个 :clearance 键
Clearance::RackSession.new(Rails.application).call(req.env)
从这里开始,找到当前用户很简单:
req.env[:clearance]&.current_user
其中 returns User 的实例(继承自 ApplicationRecord)
提出了一些问题
对每个请求执行此操作会导致堆栈太深错误:
Clearance::RackSession.new(Rails.application).call(req.env) unless 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)
完整内容请参阅上面的最终代码部分。我还想重复一下 我不知道这个 的安全隐患,或者如果有的话。
我正在寻找一种方法来在 Rails 日志中的每一行显示当前用户。例如。 [johndoe] 于 2020 年 6 月 7 日开始为 127.0.0.1 获取“/”01:10:33 +0000
一些研究建议使用 rails config.log_tags 设置
(我想出了一个解决方案,但我完全不知道这是否会带来安全后果)。
我发现了一些想法,涉及通过会话和 cookie 查找用户 ID。这对清关无效 req.env 不包含相同的数据。
- http://blog.simontaranto.com/post/2018-05-18-better-rails-logs-current-user-request-context.html/
- How to log user_name in Rails?
最终代码
req 是 ActionDispatch::Request 的实例,它是在您加载网页时创建的。您可以在 config.log_tags 中使用 Proc(通常在 config/application.rb 或 config/environments/.rb 中设置),如下所示:
config.log_tags = [
->(req) { User.current_user_from_request(req) }
]
User.current_user_from_request(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 和方法调用(env) 从 cookie 中读取以前存在的会话并在每次响应时维护 cookie。
此代码为 req.env 添加了一个 :clearance 键
Clearance::RackSession.new(Rails.application).call(req.env)
从这里开始,找到当前用户很简单:
req.env[:clearance]&.current_user
其中 returns User 的实例(继承自 ApplicationRecord)
提出了一些问题
对每个请求执行此操作会导致堆栈太深错误:
Clearance::RackSession.new(Rails.application).call(req.env) unless 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)
完整内容请参阅上面的最终代码部分。我还想重复一下 我不知道这个 的安全隐患,或者如果有的话。