مصادقة مريحة: السماح بتسجيل الدخول من أجهزة كمبيوتر متعددة؟

StackOverflow https://stackoverflow.com/questions/1848252

سؤال

يستخدم تطبيق القضبان لدينا مصادقة مريحة لإدارة المستخدم / الجلسة ويبدو أن تسجيل الدخول إلى نفس الحساب من أجهزة كمبيوتر متعددة تقضي الجلسة على أجهزة الكمبيوتر الأخرى، مما يؤدي إلى مقتل ميزة "تذكرني".

لذلك قل أنا في المنزل وتسجيل الدخول إلى التطبيق (والتحقق من "تذكرني"). ثم أذهب إلى المكتب وتسجيل الدخول (وأيضا تحقق من "تذكرني"). بعد ذلك، عندما أعود إلى المنزل، أعود إلى التطبيق وعلاوة على إعادة تسجيل الدخول.

كيف يمكنني السماح بتسجيل الدخول من آلات متعددة والحفاظ على وظائف "تذكرني" العمل عبرها جميعا؟

هل كانت مفيدة؟

المحلول

سوف تضحي بعض الأمن من خلال القيام بذلك، لكنها بالتأكيد ممكنة. هناك طريقتان يجب أن تكون قادرا على تحقيق ذلك.

في الأول، يمكنك تجاوز طريقة Make_Token في نموذج المستخدم الخاص بك. يتم تنفيذ النموذج حاليا على النحو التالي.

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

في كل مرة يقوم فيها المستخدم بتسجيل الدخول، مع أو بدون ملف تعريف الارتباط، 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, ، و forget_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

الثلاثة من هذه الأساليب إعادة تعيين الرمز المميز. forget_me يحددها إلى nil, ، في حين أن اثنين آخران وضعه على القيمة التي تم إرجاعها make_token. وبعد يمكنك تجاوز هذه الأساليب في طراز المستخدم، لمنعها من إعادة تعيين الرمز المميز إذا كان موجودا وليس منتهية الصلاحية. ربما هذا هو أفضل نهج، أو يمكنك إضافة بعض المنطق الإضافي إلى handle_remember_cookie! الطريقة، على الرغم من أن ذلك من المحتمل أن يكون أكثر عمل.

لو كنت أنت، وأود أن تجاوز remember_me_until, forget_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

لاحظ أنه من خلال القيام بذلك، فأنت تقوم بإخراج الميزات التي تحميك عن سرقة الرمز المميز. ولكن هذا قرار فائدة التكلفة يمكنك القيام به.

نصائح أخرى

يمكنك تغيير ما remember_token هو تحقيق هذا. يمكنك ضبطه على:

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

بدلا من

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

الآن لا يوجد شيء كمبيوتر أو وقت محدد حول الرمز المميز ويمكنك البقاء مسجلا من أجهزة متعددة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top