Я использую Devise in Rails 3. Я хочу видеть имя current_user в production.log.Как зарегистрировать имя пользователя в Rails?
Я хотел бы настроить рельсы так:
config.log_tags = [:user_name]
Я использую Devise in Rails 3. Я хочу видеть имя current_user в production.log.Как зарегистрировать имя пользователя в Rails?
Я хотел бы настроить рельсы так:
config.log_tags = [:user_name]
Я нашел это небольшое сложное, но работающее решение.
Warden хранит информацию о пользователе в сеансе, но req.session недоступна для ведения журнала.
Таким образом, вы должны добавить это в конфиг/application.rb
config.middleware.delete(ActionDispatch::Cookies)
config.middleware.delete(ActionDispatch::Session::CookieStore)
config.middleware.insert_before(Rails::Rack::Logger, ActionDispatch::Session::CookieStore)
config.middleware.insert_before(ActionDispatch::Session::CookieStore, ActionDispatch::Cookies)
Затем создайте файл конфигурации/инициализаторами/протоколирования.RB
Rails.configuration.log_tags = [
proc do |req|
if req.session["warden.user.user.key"].nil?
"Anonym"
else
"user_id:#{req.session["warden.user.user.key"][0][0]}"
end
end
]
Теперь я вижу, это для Anonymous:
[Anonym] Served asset ...
и это для пользователя:
[user_id:1] Served asset ...
@CharlesBergeron Вы выяснили, подходит ли этот подход или нет? – rit
@rit Да, пошел с вставляя наш собственный пользовательский протоколирования Middleware, как это: 'require_relative» ../ Библиотека/my_app/log_user_id'' 'config.middleware.insert_after (ActiveRecord :: SessionStore, MyApp :: LogUserId) ' –
@CharlesBergeron Спасибо! – rit
К сожалению войти теги оцениваются только один раз в самом начале запроса делегации (в Rails::Rack::Logger
промежуточного слоя). На этом этапе контроллер отсутствует, поэтому никакой помощник current_user пока недоступен. Нет еще начальника или даже сеанса, но, по крайней мере, есть cookiejar, поэтому, если вы храните свой session_id, вы можете напрямую восстановить сеанс или log session_id.
config.log_tags = [ lambda { |req| req.cookie_jar["_session_id"].to_s } ]
Я думаю, что лучшей альтернативой является сохранение имени пользователя в файле cookie непосредственно в log_in и уничтожение его сеансом.
config.log_tags = [ lambda { |req| req.cookie_jar["user_name"] || 'Noone' } ]
НЕ РАБОТАЕТ:
Но если вы используете завещать, он использует Warden raack промежуточное программное обеспечение, так env['warden']
должны быть доступны, так что вы можете попробовать?
config.log_tags = [ lambda { |req| user = req.env['warden'].user; user && user.name || 'Noone'; } ]
Даже без надзирателя, поскольку у вас есть сеанс можно получить через env['rack.session']
, если хранить идентификатор пользователя в сессии, вы можете сделать что-то вроде
config.log_tags = [ lambda { |req| user = User.find_by_id(req.env['rack.session']['user_id']); user && user.name || 'Noone'; }
Вот что я просто добавил к config/initializers/logging.rb
:
Rails.configuration.log_tags = [
:uuid, # request UUID
lambda { |req|
# Credentials are (currently) in the format of:
#
# <session_hash>::<user_id>
#
# So we have to split by '::' to obtain the user_id for logging.
#
# This will just output "User: nil" if there is no current session.
"User: #{req.cookies['user_credentials'].to_s.split('::')[1]}"
}
]
Это для Authlogic. То, что вам нужно сделать, может отличаться, поэтому вам действительно нужно вникнуть и посмотреть, что ваши данные предоставляют вам.
Шаг 1:
Посмотрите, что req
объект имеет в наличии. Добавьте к этому config/initializers/logging.rb
:
Rails.configuration.log_tags = [
lambda { |req|
req.inspect
}
]
Затем нажмите страницу и посмотреть, что получает сбрасывали.
Шаг 2: Смотрите, если ваши куки имеют достаточно информации, используя ту же технику:
Rails.configuration.log_tags = [
lambda { |req|
req.cookies.inspect
}
]
(хит запроса)
В стороне: Не беспокоиться о вводе в именах пользователей/сообщений электронной почты в логах - идентификатор пользователя достаточно хорош, и вы можете найти его в базе данных, чтобы получить какие-либо дополнительные метаданные, которые вам нужны.
Спасибо за ответ. К сожалению, Devise не использует файлы cookie для хранения пользовательской информации. – boblin
В Rails 4 encrypted_cookie_store является хранилище сеансов по умолчанию. Это, как вы можете получить доступ к данным сеанса:
session_data = req.cookie_jar.signed[ "_qnaire_session" ]
И это выглядит как warden_data выглядит по-разному в моем новом приложении, например .: [[542], "$2a$10$e5aYxr/PIp6OOj8jzE7mke"]
, где первый элемент является идентификатор пользователя.
Вот мой текущий фрагмент: https://gist.github.com/wojt-eu/5109643
Это то, что я придумал:
config.log_tags = [
:remote_ip,
->(req){
session_data = req.cookie_jar.signed[ "_qnaire_session" ]
warden_data = session_data["warden.user.provider_user.key"]
if warden_data
'#' + warden_data[1][0].to_s
else
"guest"
end
}
]
_qnaire_session
может быть заменен instance.config.session_options[:key]
или через синглтон: Rails.application.config.session_options[:key]
У меня есть модель ProviderUser, следовательно warden.user.provider_user.key
, Я полагаю, что с моделью Пользователя это будет warden.user.user.key
.
Это грязно, но это не влияет на обычный процесс аутентификации, порядок стеков промежуточного программного обеспечения и т. Д. Если он ломается во время некоторого обновления, будут затронуты только тегированные журналы, которые я должен заметить при просмотре журналов разработки.
Является ли «qnaire» для «анкеты»? –
@AndrewGrimm yes (-: –
Как @viktortron сказал в his answer на log_tags
время инициализации мы не имеем надлежащего session
Objet доступны, но session_id
в запросе.
Если вы используете _database session_store_, так как это мой случай, вы можете восстановить сеанса Ad-Hoc:
session = ActiveRecord::SessionStore::Session.find_by_session_id(request.cookie_jar["_session_id"])
Это как мой log_tags
определены:
# config/initializers/rails_log.rb
def get_user_id(req)
session = ActiveRecord::SessionStore::Session.find_by_session_id(req.cookie_jar["_session_id"])
result = session ? session.data["user_id"] : 0
"%07d" % result
end
log_tags = []
log_tags << lambda { |req| Time.now.strftime("%F %T.%L") }
log_tags << lambda { |req| req.uuid.first(8) }
log_tags << lambda { |req| get_user_id(req) }
Rails.configuration.log_tags = log_tags
В результате чего-то вроде:
[2013-01-22 13:51:36.659] [e52435d1] [0036484] <the log line>
А теперь кое-что совсем другое ...
https://github.com/roidrage/lograge/issues/23#issuecomment-11709861
Я просто попытался это с Rails 4, последней Завещания и Lograge.
Лучший способ пойти. Спасибо –
Для тех, кто, используя ответ REDIS :: Сторож @ fjuillen выглядит следующим образом:
redis = Redis::Store.new
redis.select 3 # only if you use a different database
result = redis.get req.cookie_jar["_session_id"]
протестирован на рельсах 4.
В качестве быстрого и уродливого обходного пути, возможно, можно было бы зарегистрировать вторую строку после обработки запроса.
Это 500 ServerError было представлено: # {имя пользователя}
Я использовал это решение от Войтек Крушевских: https://gist.github.com/WojtekKruszewski
Я подправили немного для моего проекта, чтобы включать только идентификатор, но в основном то же самое ,
# config/application.rb
config.log_tags = [
->(req){
if user_id = WardenTaggedLogger.extract_user_id_from_request(req)
user_id.to_s
else
"?"
end
}
]
И создать этот инициализатор
# initializers/warden_tagged_logger.rb
module WardenTaggedLogger
def self.extract_user_id_from_request(req)
session_key = Rails.application.config.session_options[:key]
session_data = req.cookie_jar.encrypted[session_key]
warden_data = session_data["warden.user.user.key"]
warden_data[0][0]
rescue
nil
end
end
Это самый чистый подход. – Fabio
Я использую Swards solution и он работает как шарм. Однако используя begin..rescue
вместо Hash # has_key? является производительность убийца
require 'benchmark/ips'
good_hash = { 'warden.user.admin_user.key' => [[1]]}
bad_hash = {}
Benchmark.ips do |x|
x.report('begin+rescue good hash') { good_hash['warden.user.admin_user.key'][0][0] }
x.report('has_key good hash') do
good_hash.has_key?('warden.user.admin_user.key') &&
good_hash['warden.user.admin_user.key'][0][0]
end
x.report('begin+rescue bad hash') { bad_hash['warden.user.admin_user.key'][0][0] rescue nil }
x.report('has_key bad hash') do
if bad_hash.has_key?('warden.user.admin_user.key')
bad_hash['warden.user.admin_user.key'][0][0]
end
end
# Compare the iterations per second of the various reports!
x.compare!
end
Результаты говорят сами за себя
Comparison:
has_key bad hash: 4870164.1 i/s
begin+rescue good hash: 3544134.7 i/s - 1.37x slower
has_key good hash: 2127500.6 i/s - 2.29x slower
begin+rescue bad hash: 4468.2 i/s - 1089.95x slower
Что почти работал для меня (Rails 3.2.22.2) ответ здесь: http://benjit.com/rails/logger/2016/02/26/getting-admin-user-into-rails-logfile/
Это предполагает, что объект cookie_jar
отвечает на encrypted
. Однако для меня это было не так. Что в конечном счете работал для меня заключается в следующем:
config/initializers/logging.rb
:
Rails.configuration.log_tags = [
lambda { |req|
session_key = Rails.application.config.session_options[:key]
session_data = req.cookie_jar.signed[Rails.application.config.session_options[:key] ]
warden_data = (session_data["warden.user.user.key"]|| [[]])
admin_user = warden_data[0][0]
"u: #{admin_user || 0}"
}
]
Вот печенье Decrypter я использую в Rails 5.1 помечать журналы с user_id
, который хранится в куки. Это в основном позволяет мне получать доступ к контроллеру эквиваленту session[:user_id]
из сырого печенья
сред/production.rb:
config.log_tags = [
:request_id,
:remote_ip,
lambda do |req|
session_data = CookieDecrypter.new(req).session_data
"user_id:#{session_data['user_id']}"
end
]
приложения/модели/cookie_decrypter.rb:
class CookieDecrypter
attr_reader :request
def initialize(request)
@request = request
end
def session_data
cookie = request.cookies[session_key]
return {} unless cookie.present?
cookie = CGI::unescape(cookie)
key_generator = ActiveSupport::KeyGenerator.new(secret_key_base, iterations: 1000)
secret = key_generator.generate_key(salt)[0, ActiveSupport::MessageEncryptor.key_len]
sign_secret = key_generator.generate_key(signed_salt)
encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret, serializer: JSON)
encryptor.decrypt_and_verify(cookie) || {}
end
private
def session_key
Rails.application.config.session_options[:key]
end
def secret_key_base
Rails.application.secrets[:secret_key_base]
end
def salt
Rails.application.config.action_dispatch.encrypted_cookie_salt
end
def signed_salt
Rails.application.config.action_dispatch.encrypted_signed_cookie_salt
end
end
никаких новостей по этому поводу? –
Я использую https://github.com/roidrage/lograge для этого – aceofspades