microdot.login — flux de autentificare a utilizatorului

Un wrapper de nivel mai înalt în jurul microdot.session care implementează fluxul convențional de autentificare cu nume de utilizator / parolă: o funcție de retroapelare (callback) user loader mapează id-ul de utilizator stocat în sesiune înapoi la obiectul utilizator al aplicației, decoratorii de rute redirecționează cererile neautentificate către un URL de autentificare configurabil, iar cookie-urile opționale „remember me” permit vizitatorilor care revin să rămână autentificați între sesiunile de browser.

Necesită ca microdot.session să fie inițializat pe aplicație înainte de construirea obiectului de autentificare – sesiunea este locul unde se stochează id-ul de utilizator.

class Login

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

URL-ul către care decoratorul redirecționează cererile neautentificate. Aplicația furnizează formularul/handlerul efectiv de autentificare la această rută. Implicit '/login'.

user_loader(f)

Decorator care înregistrează funcția de retroapelare (callback) de rezolvare a utilizatorului. f primește id-ul de utilizator stocat în sesiune și returnează obiectul utilizator (sau None dacă id-ul nu mai este valid – un cont șters, o sesiune revocată etc.).

login = Login()

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

Decorarea unei rute cu instanța Login o restricționează în spatele autentificării:

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

Cererile neautentificate sunt redirecționate către login_url cu un parametru de interogare ?next=<original-url> astfel încât handlerul de autentificare să poată trimite utilizatorul înapoi de unde a venit.

fresh(f)

Asemănător cu __call__(), dar respinge sesiunile restaurate dintr-un cookie „remember me” – utilizatorul trebuie să se fi autentificat explicit de la ultima autentificare completă. Folosit pentru a restricționa rutele sensibile (schimbarea parolei, ștergerea contului) astfel încât un cookie remember-me furat să nu le poată accesa.

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

Marchează utilizatorul user ca autentificat pentru cererea request. Stochează id-ul de utilizator în sesiune și returnează un răspuns de redirecționare.

user

Obiectul utilizator returnat de user loader. Trebuie să aibă un atribut id.

remember

Dacă este adevărat, setează de asemenea un cookie _remember cu durată lungă de viață. Trimite True pentru cele 30 de zile implicite sau un întreg pentru numărul de zile cât ar trebui să dureze cookie-ul.

redirect_url

Unde să redirecționeze după autentificare. Suprascris de ?next=<url> din cererea originală dacă indică o cale same-site.

Returnează răspunsul de redirecționare – returnează valoarea sa din handlerul rutei de autentificare.

async logout_user(request)

Șterge id-ul de utilizator din sesiune și elimină orice cookie _remember. Folosește dintr-o rută /logout

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

Returnează obiectul utilizator autentificat în prezent (sau None). Memoizat în request.g.current_user astfel încât apelurile repetate într-o singură cerere accesează loaderul o singură dată.

Exemplu

Un flux minim de autentificare:

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-ul _remember este el însuși un JWT semnat (folosind secretul sesiunii), astfel încât un cookie furat nu poate fi reutilizat pe o altă aplicație sau după ce secretul a fost rotit.