2012-05-30 18 views

Odpowiedz

21

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 ... 
+0

@CharlesBergeron Czy wiesz, czy to podejście jest w porządku, czy nie? – rit

+1

@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) ' –

+0

@CharlesBergeron Dzięki! – rit

2

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'; } 
+0

Dziękuję za odpowiedź. Próbowałem twojego pierwszego przykładu, ale to nie działa dla mnie. Otrzymuję komunikat "Błąd wewnętrznego serwera". – boblin

+0

co powiesz teraz? channge to req.env –

+0

Brakuje również ostatecznego "]", ale nadal otrzymuję komunikat "Wewnętrzny błąd serwera". – boblin

2

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.

+0

Dziękujemy za odpowiedź. Niestety Devise nie wykorzystuje plików cookie do przechowywania informacji o użytkowniku. – boblin

5

Dodano 07.03.2013:

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

Poprzednia wersja:

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.

+0

Czy "qnaire" jest skrótem od "questionnaire"? –

+1

@AndrewGrimm yes (-: –

1

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> 
-2

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.

0

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}

12

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 
+0

To jest najczystsze podejście. – Fabio

1

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 
1

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}" 
    } 
] 
1

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 
Powiązane problemy