2012-05-22 14 views
24

में उपयोगकर्ता_लोडर कॉलबैक को कैसे कार्यान्वित करें मैं फ्लास्क ऐप में उपयोगकर्ता प्रमाणीकरण को लागू करने के लिए फ्लास्क और Flask-Login एक्सटेंशन का उपयोग करने का प्रयास कर रहा हूं। लक्ष्य डेटाबेस से उपयोगकर्ता खाता जानकारी खींचना है और फिर उपयोगकर्ता में लॉग इन करना है, लेकिन मैं अटक गया हूं; हालांकि, मैंने इसे फ्लास्क-लॉगिन व्यवहार के एक विशेष भाग तक सीमित कर दिया है।Flask-Login

Flask-Login documentation के अनुसार, मुझे उपयोगकर्ता_लोडर "कॉलबैक" फ़ंक्शन बनाने की आवश्यकता है। इस फ़ंक्शन के वास्तविक उद्देश्य और कार्यान्वयन ने मुझे कुछ दिनों के लिए भ्रमित कर दिया है:

आपको उपयोगकर्ता_लोडर कॉलबैक प्रदान करने की आवश्यकता होगी। सत्र में संग्रहीत उपयोगकर्ता आईडी से उपयोगकर्ता ऑब्जेक्ट को पुनः लोड करने के लिए इस कॉलबैक का उपयोग किया जाता है। यह किसी उपयोगकर्ता की यूनिकोड आईडी लेना चाहिए, और संबंधित उपयोगकर्ता ऑब्जेक्ट को वापस लेना चाहिए। उदाहरण के लिए:

@login_manager.user_loader 
def load_user(userid): 
    return User.get(userid) 

अब, मैं उपयोगकर्ता, एक रूप में एक नाम और पासवर्ड दर्ज डेटाबेस के आधार पर जाँच, और उपयोगकर्ता के लिए लॉग इन करना चाहते हैं। डेटाबेस सामान ठीक काम करता है और मेरे लिए कोई समस्या नहीं है।

यह 'कॉलबैक' फ़ंक्शन उपयोगकर्ता आईडी # पारित करना चाहता है, और उपयोगकर्ता ऑब्जेक्ट (जिस सामग्री की मैं डेटाबेस से लोड कर रहा हूं) वापस कराना चाहता हूं। लेकिन मुझे वास्तव में यह नहीं मिलता है कि यह जांच/कर रहा है, क्योंकि उपयोगकर्ता आईडी सभी को एक ही स्थान से खींच लिया जाता है। मैं कॉलबैक को काम करने के लिए 'सॉर्ट-ऑफ' कर सकता हूं, लेकिन यह गन्दा/हैकिश लगता है और यह ब्राउजर अनुरोधों के हर संसाधन के साथ डेटाबेस को हिट करता है। मैं वास्तव में प्रत्येक पृष्ठ रीफ्रेश के साथ favicon.ico डाउनलोड करने के लिए अपना डेटाबेस जांचना नहीं चाहता, लेकिन फ्लास्क-लॉगिन ऐसा लगता है कि यह इसे मजबूर कर रहा है।

यदि मैं डेटाबेस को दोबारा जांच नहीं करता, तो मेरे पास इस फ़ंक्शन से उपयोगकर्ता ऑब्जेक्ट को वापस करने का कोई तरीका नहीं है। लॉग इन करने के लिए फ्लास्क रूट में उपयोगकर्ता ऑब्जेक्ट/क्लास बनाया जाता है, और इस प्रकार कॉलबैक के दायरे से बाहर होता है।

मुझे यह पता नहीं लगा सकता कि उपयोगकर्ता कॉल को इस कॉलबैक फ़ंक्शन में कैसे पास किया जाए, बिना किसी डेटाबेस को हिट किए। या, अन्यथा यह समझें कि इसे और अधिक प्रभावी तरीके से कैसे किया जाए। मुझे कुछ मौलिक याद आना चाहिए, लेकिन मैं कुछ दिनों के लिए इस पर घूर रहा हूं, इस पर सभी प्रकार के कार्यों और तरीकों को फेंक रहा हूं, और कुछ भी काम नहीं कर रहा है।

यहां मेरे परीक्षण कोड से प्रासंगिक स्निपेट हैं। उपयोगकर्ता वर्ग:

class UserClass(UserMixin): 
    def __init__(self, name, id, active=True): 
      self.name = name 
      self.id = id 
      self.active = active 

    def is_active(self): 
      return self.active 

समारोह मैं कुप्पी के लॉग इन के user_loader कॉलबैक फ़ंक्शन पर उपयोगकर्ता ऑब्जेक्ट प्रदान करने के लिए बनाया:

def check_db(userid): 

    # query database (again), just so we can pass an object to the callback 
    db_check = users_collection.find_one({ 'userid' : userid }) 
    UserObject = UserClass(db_check['username'], userid, active=True) 
    if userObject.id == userid: 
      return UserObject 
    else: 
      return None 

'कॉलबैक' है, जो मैं पूरी तरह समझ में नहीं आता (लौटना चाहिए उपयोगकर्ता वस्तु है, जो डेटाबेस से खींचने के बाद बनाया जाता है):

@login_manager.user_loader 
def load_user(id): 
    return check_db(id) 

लॉगिन मार्ग:

@app.route("/login", methods=["GET", "POST"]) 
def login(): 
    if request.method == "POST" and "username" in request.form: 
      username = request.form["username"] 

      # check MongoDB for the existence of the entered username 
      db_result = users_collection.find_one({ 'username' : username }) 

      result_id = int(db_result['userid']) 

      # create User object/instance 
      User = UserClass(db_result['username'], result_id, active=True) 

      # if username entered matches database, log user in 
      if username == db_result['username']: 
       # log user in, 
       login_user(User) 
       return url_for("index")) 
      else: 
       flash("Invalid username.") 
     else: 
      flash(u"Invalid login.") 
     return render_template("login.html") 

मेरा कोड 'kinda' काम करता है, मैं लॉग इन और आउट कर सकता हूं, लेकिन जैसा कि मैंने कहा था, इसे पूरी तरह से डेटाबेस के लिए डेटाबेस को हिट करना होगा, क्योंकि मुझे कॉलबैक फ़ंक्शन को एक अलग नेमस्पेस/स्कोप में उपयोगकर्ता ऑब्जेक्ट प्रदान करना होगा जहां से बाकी लॉगिन कार्रवाई होती है। मुझे पूरा यकीन है कि मैं इसे सब गलत कर रहा हूं, लेकिन मैं यह नहीं समझ सकता कि कैसे।

फ्लास्क-लॉगिन does it this way द्वारा प्रदान किया गया उदाहरण कोड, लेकिन यह केवल काम करता है क्योंकि यह वैश्विक हार्ड-कोडित शब्दकोश से उपयोगकर्ता ऑब्जेक्ट खींच रहा है, न कि एक वास्तविक दुनिया परिदृश्य में डेटाबेस जैसे, जहां डीबी की जांच की जानी चाहिए और उपयोगकर्ता ऑब्जेक्ट्स के बाद बनाया गया उपयोगकर्ता उपयोगकर्ता अपने लॉगिन प्रमाण-पत्र दर्ज करता है। और मुझे कोई अन्य उदाहरण कोड नहीं दिख रहा है जो फ्लास्क-लॉगिन के साथ डेटाबेस का उपयोग करके दिखाता है।

यहां क्या याद आ रही है?

+0

कितना अजीब। आपका लॉगिन() किसी भी पासवर्ड की जांच भी नहीं करता है। – Houman

+2

@ हुमन यह केवल उदाहरण उद्देश्यों के लिए था। –

उत्तर

16

आपको प्रत्येक अनुरोध पर उपयोगकर्ता ऑब्जेक्ट को डीबी से लोड करने की आवश्यकता होगी। उस आवश्यकता के लिए सबसे मजबूत कारण यह है कि फ्लास्क-लॉगिन इसकी निरंतर वैधता सुनिश्चित करने के लिए हर बार प्रमाणीकरण टोकन की जांच करेगा। इस टोकन की गणना उपयोगकर्ता ऑब्जेक्ट पर संग्रहीत पैरामीटर की आवश्यकता हो सकती है।

उदाहरण के लिए, मान लीजिए कि उपयोगकर्ता के दो समवर्ती सत्र हैं। उनमें से एक में, उपयोगकर्ता अपना पासवर्ड बदलता है। बाद के अनुरोधों में, उपयोगकर्ता को दूसरे सत्र से लॉग आउट होना चाहिए और आपके एप्लिकेशन को सुरक्षित होने के लिए नया लॉगिन करने के लिए मजबूर होना चाहिए। उस मामले के बारे में सोचें जहां दूसरा सत्र चोरी हो गया है क्योंकि आपका उपयोगकर्ता किसी कंप्यूटर से लॉग आउट करना भूल गया है - आप स्थिति को तुरंत ठीक करने के लिए पासवर्ड बदलना चाहते हैं। आप अपने व्यवस्थापक को उपयोगकर्ता को बाहर निकालने की क्षमता भी दे सकते हैं।

ऐसा करने के लिए मजबूर लॉगआउट होने के लिए, कुकी में संग्रहीत प्रमाणीकरण टोकन 1) पासवर्ड पर या कुछ और नया पासवर्ड सेट होने पर बदलता है; 2) उपयोगकर्ता ऑब्जेक्ट के नवीनतम ज्ञात विशेषताओं के विरुद्ध किसी भी दृश्य को चलाने से पहले जांचें - जो डीबी में संग्रहीत हैं।

+1

उस स्पष्टीकरण के लिए धन्यवाद। इसलिए यह जरूरी नहीं है कि मेरा दृष्टिकोण/समाधान अब तक गलत था, बल्कि इसके बजाय मैंने कुछ गलत धारणाएं की कि यह इस तरह से क्यों काम कर रहा था। –