microdot.login — proces přihlášení uživatele

Obal vyšší úrovně nad microdot.session, který implementuje konvenční proces přihlášení pomocí uživatelského jména / hesla: callback user loader mapuje uživatelské id uložené v relaci zpět na uživatelský objekt aplikace, dekorátory tras přesměrovávají neautentizované požadavky na konfigurovatelnou přihlašovací URL a volitelné cookies „remember me“ umožňují vracejícím se návštěvníkům zůstat přihlášeni napříč relacemi prohlížeče.

Vyžaduje, aby byl microdot.session inicializován v aplikaci před tím, než je sestaven přihlašovací objekt – relace je místo, kde je uloženo uživatelské id.

class Login

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

URL, na kterou dekorátor přesměrovává neautentizované požadavky. Aplikace na této trase poskytuje skutečný přihlašovací formulář/handler. Výchozí '/login'.

user_loader(f)

Dekorátor, který registruje callback pro rozlišení uživatele. f přijímá uživatelské id uložené v relaci a vrací uživatelský objekt (nebo None, pokud již id není platné – smazaný účet, odvolaná relace atd.).

login = Login()

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

Dekorování trasy instancí Login ji chrání za autentizací:

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

Neautentizované požadavky jsou přesměrovány na login_url s parametrem dotazu ?next=<original-url>, aby handler přihlášení mohl uživatele poslat zpět tam, odkud přišel.

fresh(f)

Jako __call__(), ale odmítá relace obnovené z cookie „remember me“ – uživatel se musel od posledního úplného přihlášení explicitně přihlásit. Používá se k ochraně citlivých tras (změna hesla, smazání účtu), aby je odcizená remember-me cookie nemohla dosáhnout.

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

Označí uživatele user jako přihlášeného pro request. Uloží uživatelské id do relace a vrátí odpověď s přesměrováním.

user

Uživatelský objekt vrácený funkcí user loader. Musí mít atribut id.

remember

Pokud je pravdivý, nastaví také dlouhodobou cookie _remember. Předejte True pro výchozích 30 dní, nebo celé číslo pro počet dní, po které má cookie trvat.

redirect_url

Kam přesměrovat po přihlášení. Přepsáno pomocí ?next=<url> z původního požadavku, pokud ukazuje na cestu na stejném webu.

Vrátí odpověď s přesměrováním – vraťte její hodnotu z handleru přihlašovací trasy.

async logout_user(request)

Vymaže uživatelské id z relace a odstraní případnou cookie _remember. Použijte z trasy /logout

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

Vrátí objekt aktuálně přihlášeného uživatele (nebo None). Memoizováno v request.g.current_user, takže opakovaná volání v rámci jednoho požadavku zasáhnou loader jen jednou.

Příklad

Minimální proces přihlášení:

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 je sama o sobě podepsaný JWT (pomocí tajného klíče relace), takže odcizenou cookie nelze znovu použít v jiné aplikaci ani poté, co byl tajný klíč obměněn.