2009-12-04 6 views
6

हमारा रेल ऐप उपयोगकर्ता/सत्र प्रबंधन के लिए त्वरित प्रमाणीकरण का उपयोग कर रहा है और ऐसा लगता है कि एकाधिक कंप्यूटरों से एक ही खाते में लॉग इन करना अन्य कंप्यूटरों पर सत्र को मारता है, इस प्रकार "मुझे याद रखें" सुविधा को मारता है।आराम प्रमाणीकरण: एकाधिक कंप्यूटर से लॉग इन की अनुमति दें?

तो कहें कि मैं घर पर हूं और ऐप में लॉग इन करता हूं (और "मुझे याद रखें" की जांच करें)। फिर मैं कार्यालय जाता हूं और लॉग इन करता हूं (और "मुझे याद रखें" भी जांचें)। फिर, जब मैं घर लौटता हूं, तो मैं ऐप पर वापस आ जाता हूं और उसे फिर से लॉग इन करना पड़ता है।

मैं एकाधिक मशीनों से लॉग इन करने की अनुमति कैसे दे सकता हूं और उन सभी पर काम कर रहे "मुझे याद रखें" कार्यक्षमता को कैसे रख सकता हूं?

उत्तर

9

आप ऐसा करके कुछ सुरक्षा बलिदान करने जा रहे हैं, लेकिन यह निश्चित रूप से संभव है। इसे पूरा करने में सक्षम होने के दो तरीके हैं।

पहले, आप अपने उपयोगकर्ता मॉडल में 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 

इससे यह सुनिश्चित होता है कि टोकन कभी नहीं बदलता, लेकिन यह भी किसी को भी उस टोकन प्रयोक्ता का रूप धारण करने के लिए मिल गया सक्षम होगा।

इसके अलावा, यदि आप authenticated_system.rb फ़ाइल में handle_remember_cookie! विधि को देखें, तो आप इस विधि को आपके लिए काम करने में सक्षम होना चाहिए।

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 

ध्यान दें कि ऐसा करके, आप सुविधाओं है कि आप टोकन चोरी से बचाने के बाहर ले जा रहे हैं। लेकिन यह एक लागत लाभ निर्णय है जिसे आप कर सकते हैं।

+0

धन्यवाद एक टन! तो उपयोगकर्ता को "मुझे याद रखें" की जांच करने की कार्यक्षमता अब कैसे काम करती है? क्या यह अभी भी उन्हें 'remember_me' विधि में निर्धारित समय के लिए याद है? – Shpigford

+0

यह अभी भी याद है कि mem_me विधि में 2 सप्ताह के लिए, लेकिन टोकन का उपयोग पहली बार शुरू होता है। दूसरे शब्दों में, यदि आप कंप्यूटर ए से लॉग इन करते हैं, तो कंप्यूटर बी से 10 दिन लॉग इन करें, 4 दिन बाद टोकन दोनों कंप्यूटरों पर समाप्त हो जाता है। – jcnnghm

+0

ग्रेट। आपकी सहायता के लिए एक बार फिर से धन्यवाद! – Shpigford

0

आप इसे प्राप्त करने के लिए remember_token क्या बदल सकते हैं। आप इसे करने के लिए सेट कर सकते हैं:

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

बजाय

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

अब वहाँ कुछ भी नहीं कंप्यूटर या समय टोकन के बारे में विशिष्ट है और आप एक से अधिक मशीनों से में लॉग इन रह सकते हैं।

+0

हम्म, आप किस प्रमाणीकरण के प्रमाणीकरण का संस्करण कर रहे हैं? मैं एक सुंदर हालिया संस्करण का उपयोग कर रहा हूं और 'remember_token' कई जटिल जटिल तरीकों और SHA1 एन्क्रिप्शन के साथ सेट है। – Shpigford

+1

आह, क्षमा करें। यह एक बहुत पुराना संस्करण है जिसे मैंने कम से कम एक वर्ष तक चलाया है। यह नहीं पता था कि यह इतना बदल गया था। – erik