Успокоительная Аутентификация: Позволить логины от нескольких компьютеров?

Я помещу свой дюйм за 0,02$. Иногда Вы волнуете необходимость добавить "наконец" позже в Вашем коде (потому что, кто когда-нибудь пишет их коду отлично первый раз?). В тех случаях внезапно имеет больше смысла иметь попытку/выгоду вне цикла. Например:

try {
    for(int i = 0; i < max; i++) {
        String myString = ...;
        float myNum = Float.parseFloat(myString);
        dbConnection.update("MY_FLOATS","INDEX",i,"VALUE",myNum);
    }
} catch (NumberFormatException ex) {
    return null;
} finally {
    dbConnection.release();  // Always release DB connection, even if transaction fails.
}

, поскольку, если Вы получаете ошибку, или нет, Вы только хотите выпустить свое соединение с базой данных (или выбрать Ваш любимый тип другого ресурса...) однажды.

6
задан Shpigford 4 December 2009 в 17:14
поделиться

2 ответа

Вы собираетесь пожертвовать некоторой безопасностью, делая это, но это определенно возможно. Есть два способа сделать это.

Первый - вы можете переопределить метод make_token в своей пользовательской модели. В настоящее время эта модель реализована следующим образом.

def make_token
  secure_digest(Time.now, (1..10).map{ rand.to_s })
end

Каждый раз, когда пользователь входит в систему с или без cookie, вызывается метод make_token , который генерирует и сохраняет новый Remember_token для пользователь. Если у вас есть какое-то другое значение, уникальное для пользователя, которое невозможно угадать, вы можете заменить метод make_token .

def make_token
  secure_digest(self.some_secret_constant_value)
end

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

Кроме этого, если вы посмотрите на handle_remember_cookie! в файле authenticated_system.rb , вы сможете изменить этот метод, чтобы он работал на вас.

def handle_remember_cookie!(new_cookie_flag)
  return unless @current_<%= file_name %>
  case
  when valid_remember_cookie? then @current_<%= file_name %>.refresh_token # keeping same expiry date
  when new_cookie_flag        then @current_<%= file_name %>.remember_me 
  else                             @current_<%= file_name %>.forget_me
  end
  send_remember_cookie!
end

Вы заметите, что этот метод вызывает три метода в модели пользователя, refresh_token , Remember_me и Forgot_me .

  def remember_me
    remember_me_for 2.weeks
  end

  def remember_me_for(time)
    remember_me_until time.from_now.utc
  end

  def remember_me_until(time)
    self.remember_token_expires_at = time
    self.remember_token            = self.class.make_token
    save(false)
  end

  # 
  # Deletes the server-side record of the authentication token.  The
  # client-side (browser cookie) and server-side (this remember_token) must
  # always be deleted together.
  #
  def forget_me
    self.remember_token_expires_at = nil
    self.remember_token            = nil
    save(false)
  end

  # refresh token (keeping same expires_at) if it exists
  def refresh_token
    if remember_token?
      self.remember_token = self.class.make_token 
      save(false)      
    end
  end

Все три метода сбрасывают токен. Forgot_me устанавливает его в nil , тогда как два других устанавливают его в значение, возвращаемое make_token . Вы можете переопределить эти методы в пользовательской модели, чтобы они не сбрасывали токен, если он существует и срок его действия не истек. Это, вероятно, лучший подход, или вы могли бы добавить дополнительную логику к методу handle_remember_cookie! , хотя это, вероятно, было бы больше работы.

Если бы я был вами, Я бы переопределил Remember_me_until , Forgot_me и refresh_token в пользовательской модели. Следующее должно работать.

def remember_me_until(time)
  if remember_token?
    # a token already exists and isn't expired, so don't bother resetting it
    true
  else
    self.remember_token_expires_at = time
    self.remember_token            = self.class.make_token
    save(false)
  end
end

# 
# Deletes the server-side record of the authentication token.  The
# client-side (browser cookie) and server-side (this remember_token) must
# always be deleted together.
#
def forget_me
  # another computer may be using the token, so don't throw it out
  true
end

# refresh token (keeping same expires_at) if it exists
def refresh_token
  if remember_token?
    # don't change the token, so there is nothing to save
    true     
  end
end

Обратите внимание, что, делая это, вы убираете функции, которые защищают вас от кражи токенов. Но это решение по рентабельности, которое вы можете принять.

9
ответ дан 10 December 2019 в 02:48
поделиться

You can change what the remember_token is to achieve this. You can set it to:

self.remember_token = encrypt("#{email}--extrajunkcharsforencryption")

instead of

self.remember_token = encrypt("#{email}--#{remember_token_expires_at}")

Now there is nothing computer or time specific about the token and you can stay logged in from multiple machines.

0
ответ дан 10 December 2019 в 02:48
поделиться
Другие вопросы по тегам:

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