Używam Devise w Rails 3. Chcę zobaczyć nazwę current_user w production.log.Jak zalogować nazwę użytkownika w Railsach?
chciałbym skonfigurować szyny tak:
config.log_tags = [:user_name]
Używam Devise w Rails 3. Chcę zobaczyć nazwę current_user w production.log.Jak zalogować nazwę użytkownika w Railsach?
chciałbym skonfigurować szyny tak:
config.log_tags = [:user_name]
Znalazłem to małe, ale działające rozwiązanie.
Warden przechowuje informacje o użytkowniku w sesji, ale zlecenie to nie jest dostępne do logowania.
Więc trzeba dodać do config/environment.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)
Następnie należy utworzyć plik konfiguracyjny/inicjatorów/rejestrowanie.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
]
Teraz widzę to przez Anonymous:
[Anonym] Served asset ...
a to dla użytkownika:
[user_id:1] Served asset ...
@CharlesBergeron Czy wiesz, czy to podejście jest w porządku, czy nie? – rit
@rit Tak, poszedł z włożeniem własny zwyczaj rejestrowania Middleware tak: 'require_relative” ../ lib/my_app/log_user_id'' 'config.middleware.insert_after (ActiveRecord :: SessionStore, MojaApl :: LogUserId) ' –
@CharlesBergeron Dzięki! – rit
Niestety tagów zalogować oceniane są tylko raz na samym początku żądanie przekazania (w Rails::Rack::Logger
middleware). Na tym etapie nie ma żadnego kontrolera, więc żaden helper current_user nie jest jeszcze dostępny. Nie ma jeszcze strażnika ani nawet sesji, ale przynajmniej jest cookiejar, więc jeśli przechowujesz swój identyfikator session_id, możesz bezpośrednio przywrócić sesję lub logować session_id.
config.log_tags = [ lambda { |req| req.cookie_jar["_session_id"].to_s } ]
Myślę, że najlepszym rozwiązaniem jest, aby zapisać nazwę użytkownika w pliku cookie bezpośrednio na log_in, i zniszczyć go z sesji.
config.log_tags = [ lambda { |req| req.cookie_jar["user_name"] || 'Noone' } ]
NIE DZIAŁA:
Ale jeśli używasz opracowania, używa Warden rAAck middleware, więc env['warden']
powinny być dostępne, więc można spróbować?
config.log_tags = [ lambda { |req| user = req.env['warden'].user; user && user.name || 'Noone'; } ]
Nawet bez naczelnika, ponieważ masz sesję dostępną poprzez env['rack.session']
, jeśli przechowywania identyfikatora użytkownika w sesji, można zrobić coś takiego
config.log_tags = [ lambda { |req| user = User.find_by_id(req.env['rack.session']['user_id']); user && user.name || 'Noone'; }
Oto, co po prostu dodaje się do 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]}"
}
]
To jest dla Authlogic. To, co musisz zrobić, może się różnić, więc powinieneś naprawdę zagłębić się i zobaczyć, jakie dane już ci ujawniają.
Krok 1:
Zobacz, co obiekt req
dysponuje. Dodaj to do config/initializers/logging.rb
:
Rails.configuration.log_tags = [
lambda { |req|
req.inspect
}
]
Kliknijmy stronę i zobaczyć, co zostanie po cenach dumpingowych.
Krok 2: Sprawdź, czy Twoje Cookie Jar ma wystarczająco dużo informacji, przy użyciu tej samej techniki:
Rails.configuration.log_tags = [
lambda { |req|
req.cookies.inspect
}
]
(hit żądanie)
Na marginesie: nie martw się o wprowadzenie nazwy użytkowników/e-maile do logów - identyfikator użytkownika jest wystarczająco dobry i można wyszukać go w bazie danych, aby uzyskać wszelkie dodatkowe metadane, których potrzebujesz.
Dziękujemy za odpowiedź. Niestety Devise nie wykorzystuje plików cookie do przechowywania informacji o użytkowniku. – boblin
W Rails 4 encrypted_cookie_store jest domyślny magazyn sesji. W ten sposób można uzyskać dostęp do danych sesji:
session_data = req.cookie_jar.signed[ "_qnaire_session" ]
I wygląda na to warden_data wygląda inaczej w mojej nowej aplikacji, np .: [[542], "$2a$10$e5aYxr/PIp6OOj8jzE7mke"]
, w której pierwszy element jest identyfikator użytkownika.
Oto mój obecny fragment: https://gist.github.com/wojt-eu/5109643
To właśnie wymyśliłem:
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
można zastąpić instance.config.session_options[:key]
lub poprzez Singleton: Rails.application.config.session_options[:key]
Mam model ProviderUser, a więc warden.user.provider_user.key
. Przypuszczam, że w przypadku modelu użytkownika będzie to warden.user.user.key
.
Jest brudny, ale nie ma wpływu na normalny proces uwierzytelniania, kolejność stosów oprogramowania pośredniego itp. Jeśli ulegnie uszkodzeniu podczas jakiejś aktualizacji, wpłynie to tylko na logi znaczników, co powinienem szybko zauważyć podczas przeglądania dzienników programistycznych.
Czy "qnaire" jest skrótem od "questionnaire"? –
@AndrewGrimm yes (-: –
Jak @viktortron powiedział w his answer na log_tags
czasie inicjalizacji nie mamy właściwego session
Objet dostępne, ale session_id
jest we wniosku.
Jeśli używasz session_store_ _database, jak to jest moja sprawa, można odbudować sesji ad-hoc:
session = ActiveRecord::SessionStore::Session.find_by_session_id(request.cookie_jar["_session_id"])
ten sposób mój log_tags
są zdefiniowane:
# 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
Wynik jest podobny do:
[2013-01-22 13:51:36.659] [e52435d1] [0036484] <the log line>
A teraz coś z zupełnie innej beczki ...
https://github.com/roidrage/lograge/issues/23#issuecomment-11709861
Właśnie próbowałem z szyn 4, najnowszego opracowania i Lograge.
Najlepszy sposób na pokonanie. Dzięki –
Dla osób korzystających odpowiedź Redis :: Store @ fjuillen wygląda tak:
redis = Redis::Store.new
redis.select 3 # only if you use a different database
result = redis.get req.cookie_jar["_session_id"]
testowane na szynach 4.
Jako szybkie i brzydkie obejście problemu, być może można zalogować drugą linię po przetworzeniu żądania.
to 500 ServerError został przedstawiony przez: # {username}
Użyłem tego rozwiązania z Wojtkiem Kruszewski: https://gist.github.com/WojtekKruszewski
I manipulowane trochę dla mojego projektu obejmują jedynie identyfikator, ale w zasadzie to samo .
# config/application.rb
config.log_tags = [
->(req){
if user_id = WardenTaggedLogger.extract_user_id_from_request(req)
user_id.to_s
else
"?"
end
}
]
I utworzyć ten inicjator
# 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
To jest najczystsze podejście. – Fabio
Używam Swards solution i działa jak czar. Jednak używając begin..rescue
zamiast Hash # has_key? jest zabójcą wydajność
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
Wyniki mówią same za siebie
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
Co prawie pracował dla mnie (Szyny 3.2.22.2) jest odpowiedzią stąd: http://benjit.com/rails/logger/2016/02/26/getting-admin-user-into-rails-logfile/
ta zakłada, że obiekt cookie_jar
odpowiada na encrypted
. Jednak nie było tak dla mnie. Co ostatecznie pracował dla mnie jest następująca:
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}"
}
]
Oto rozszyfrował cookies używam w Rails 5.1 oznaczyć dzienniki z user_id
, który jest przechowywany w pliku cookie. To w zasadzie pozwala mi wejść do równowartości kontroler session[:user_id]
z surowego ciasteczka
Środowiska/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
]
app/models/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
żadnych wiadomości na ten temat? –
Używam https://github.com/roidrage/lograge dla tego – aceofspades