Вопрос по ruby-on-rails – Как войти user_name в Rails?

14

Я использую Devise в Rails 3. Я хочу видеть имя current_user в production.log.

Я хотел бы настроить рельсы, как это:

config.log_tags = [:user_name]
есть новости по этому поводу? Viktor Trón
Я используюgithub.com/roidrage/lograge за это aceofspades

Ваш Ответ

12   ответов
0

возможно, можно было бы занести вторую строку после обработки запроса.

Эта 500 ServerError была представлена: # {username}

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

https://github.com/roidrage/lograge/issues/23#issuecomment-11709861

Я только что попробовал это с Rails 4, последним Devise и Lograge.

Лучший способ пойти. Спасибо
1

Swards решение и это работает как шарм. Однако используя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
2

теги журнала оцениваются только один раз в самом начале делегирования запроса (вRails::Rack::Logger промежуточный слой). На этом этапе нет контроллера, поэтому никакой помощник current_user еще не доступен. Еще не настроен надзиратель или даже сеанс, но есть хотя бы cookiejar, поэтому, если вы сохраните там свой session_id, вы можете вместо этого восстановить сеанс или зарегистрировать 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' } ]

НЕ РАБОТАЕТ:

Но если вы используете devise, он использует промежуточное программное обеспечение 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'; }
Спасибо за ответ. Я попробовал ваш первый пример, но он не работает для меня. Я получаю "Внутренняя ошибка сервера". boblin
моя последняя идея - печенье
Также отсутствует окончательный «]», но я все еще получаю «Внутренняя ошибка сервера». boblin
Как насчет сейчас? изменить к требованию
13

https://gist.github.com/WojtekKruszewski

Я немного подправил свой проект, чтобы он включал только id, но в основном то же самое.

# 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
Это самый чистый подход.
1

который я использую в 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
2

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: посмотрите, достаточно ли информации в вашем банке с cookie, используя ту же технику:

Rails.configuration.log_tags = [
  lambda { |req|
    req.cookies.inspect
  }
]

(нажмите на запрос)

Кроме того: не беспокойтесь о добавлении имен пользователей / электронных писем в журналы - идентификатор пользователя достаточно хорош, и вы можете посмотреть его в базе данных, чтобы получить любые дополнительные метаданные, которые вам нужны.

Спасибо за ответ. К сожалению, Devise не использует куки для хранения информации о пользователях.
5
Added 2013-03-07:

нию. Вот как вы можете получить доступ к данным сеанса:

session_data = req.cookie_jar.signed[ "_qnaire_session" ]

И похоже, что warden_data выглядит по-другому в моем новом приложении, например:[[542], "$2a$10$e5aYxr/PIp6OOj8jzE7mke"]где первый элемент - это идентификатор пользователя.

Вот мой текущий фрагмент:https://gist.github.com/wojt-eu/5109643

Previous version:

Вот что я придумал:

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.

Это грязно, но это не влияет на обычный процесс аутентификации, порядок стека промежуточного программного обеспечения и т. Д. Если он нарушается во время какого-либо обновления, это затрагивает только журналы тегов, что я должен быстро заметить, просматривая журналы разработки.

Is & quot; qnaire & quot; сокращение от «вопросник»?
@AndrewGrimm да (-:
-2

: Store @ fjuillen, ответ выглядит следующим образом:

redis = Redis::Store.new
redis.select 3 # only if you use a different database
result = redis.get req.cookie_jar["_session_id"]

проверено на рельсах 4.

1

его ответ вlog_tags время инициализации у нас не правильноеsession Объект доступен, ноsession_id находится в запросе.

Если вы используете _database session_store_, как в моем случае, вы можете перестроитьsession для этого случая:

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

Warden хранит пользовательскую информацию в сеансе, но req.session недоступен для регистрации.

Таким образом, вы должны добавить это в config / 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)

Затем создайте файл config / initializers / logging.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 ...
@rit Да, мы пошли со вставкой нашего собственного промежуточного программного обеспечения для журналирования, например так:require_relative '../lib/my_app/log_user_id' config.middleware.insert_after(ActiveRecord::SessionStore, MyApp::LogUserId)
@CharlesBergeron Спасибо!
Имейте в виду, что этот подход не работает должным образом при попытке изменить параметры вашего хранилища cookie. ваши варианты будут в основном отброшены
@CharlesBergeron Вы выяснили, подходит ли этот подход или нет?

Похожие вопросы