microdot.login — תהליך התחברות משתמש

מעטפת ברמה גבוהה יותר סביב microdot.session המממשת את תהליך ההתחברות המקובל של שם משתמש / סיסמה: פונקציית callback של user loader ממפה את מזהה המשתמש המאוחסן בסשן בחזרה לאובייקט המשתמש של היישום, דקורטורים של נתיבים מפנים בקשות לא מאומתות לכתובת התחברות הניתנת להגדרה, ו-cookies אופציונליים של ”זכור אותי“ מאפשרים למבקרים חוזרים להישאר מחוברים בין סשנים של דפדפן.

דורש ש-microdot.session יאותחל על היישום לפני בניית אובייקט ההתחברות – הסשן הוא המקום שבו מאוחסן מזהה המשתמש.

class Login

class microdot.login.Login(login_url: str = '/login')
login_url

הכתובת שאליה הדקורטור מפנה בקשות לא מאומתות. היישום מספק את טופס/handler ההתחברות בפועל בנתיב זה. ברירת מחדל '/login'.

user_loader(f)

דקורטור שרושם את פונקציית ה-callback לפתרון המשתמש. f מקבל את מזהה המשתמש המאוחסן בסשן ומחזיר את אובייקט המשתמש (או None אם המזהה כבר אינו תקף – חשבון שנמחק, סשן שבוטל וכו«).

login = Login()

@login.user_loader
async def load_user(user_id):
    return users.get(user_id)
__call__(f)

קישוט נתיב עם מופע Login חוסם אותו מאחורי אימות:

@app.get('/dashboard')
@login
async def dashboard(request):
    user = request.g.current_user
    # ...

בקשות לא מאומתות מופנות אל login_url עם פרמטר שאילתה ?next=<original-url> כך שה-handler של ההתחברות יכול להחזיר את המשתמש למקום שממנו הגיע.

fresh(f)

כמו __call__(), אך דוחה סשנים ששוחזרו מ-cookie של ”זכור אותי“ – המשתמש חייב להיות מחובר במפורש מאז ההתחברות המלאה האחרונה. בשימוש לחסימת נתיבים רגישים (שינוי סיסמה, מחיקת חשבון) כך ש-cookie גנוב של זכור-אותי לא יוכל להגיע אליהם.

async login_user(request, user, remember: bool | int = False, redirect_url: str = '/')

מסמן את user כמחובר עבור request. מאחסן את מזהה המשתמש בסשן ומחזיר תגובת הפניה.

user

אובייקט המשתמש המוחזר על ידי ה-user loader. חייב להיות בעל תכונה id.

remember

אם truthy, גם מגדיר cookie _remember ארוך-טווח. העבירו True עבור ברירת המחדל של 30 ימים, או מספר שלם עבור מספר הימים שה-cookie אמור להחזיק.

redirect_url

לאן להפנות אחרי ההתחברות. נדרס על ידי ?next=<url> מהבקשה המקורית אם הוא מצביע על נתיב באותו אתר.

מחזיר את תגובת ההפניה – החזירו את ערכו מ-handler של נתיב ההתחברות.

async logout_user(request)

מנקה את מזהה המשתמש מהסשן ומסיר כל cookie _remember. השתמשו מנתיב /logout

@app.post('/logout')
async def logout(request):
    await login.logout_user(request)
    return redirect('/')
async get_current_user(request)

מחזיר את אובייקט המשתמש המחובר כעת (או None). ממוזכר ב-request.g.current_user כך שקריאות חוזרות בתוך בקשה אחת פוגעות ב-loader רק פעם אחת.

דוגמה

תהליך התחברות מינימלי:

from microdot import Microdot, redirect
from microdot.session import Session
from microdot.login import Login

app = Microdot()
Session(app, secret_key=load_secret())
login = Login()

@login.user_loader
async def load_user(user_id):
    return users.get(user_id)

@app.get('/login')
async def login_page(request):
    return Response.send_file('static/login.html')

@app.post('/login')
async def do_login(request):
    user = authenticate(request.form['user'], request.form['pass'])
    if not user:
        return redirect('/login?error=1')
    return await login.login_user(request, user, remember=True)

@app.get('/dashboard')
@login
async def dashboard(request):
    return 'hi ' + request.g.current_user.name

@app.post('/logout')
async def logout(request):
    await login.logout_user(request)
    return redirect('/')

ה-cookie _remember הוא עצמו JWT חתום (באמצעות הסוד של הסשן), כך ש-cookie גנוב לא יכול לשמש שוב ביישום אחר או לאחר שהסוד הוחלף.