microdot.login — flux de connexion utilisateur

Un wrapper de plus haut niveau autour de microdot.session qui implémente le flux de connexion conventionnel par nom d’utilisateur / mot de passe : une fonction de rappel user loader fait correspondre l’identifiant utilisateur stocké dans la session à l’objet utilisateur de l’application, des décorateurs de route redirigent les requêtes non authentifiées vers une URL de connexion configurable, et des cookies « se souvenir de moi » facultatifs permettent aux visiteurs de rester connectés d’une session de navigateur à l’autre.

Nécessite que microdot.session soit initialisé sur l’application avant la construction de l’objet de connexion – la session est l’endroit où l’identifiant utilisateur est stocké.

class Login

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

URL vers laquelle le décorateur redirige les requêtes non authentifiées. L’application fournit le formulaire/gestionnaire de connexion réel à cette route. Par défaut '/login'.

user_loader(f)

Décorateur qui enregistre la fonction de rappel de résolution d’utilisateur. f prend l’identifiant utilisateur stocké dans la session et renvoie l’objet utilisateur (ou None si l’identifiant n’est plus valide – un compte supprimé, une session révoquée, etc.).

login = Login()

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

Décorer une route avec l’instance Login la protège derrière une authentification

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

Les requêtes non authentifiées sont redirigées vers login_url avec un paramètre de requête ?next=<original-url> afin que le gestionnaire de connexion puisse renvoyer l’utilisateur là d’où il venait.

fresh(f)

Comme __call__(), mais rejette les sessions restaurées depuis un cookie « se souvenir de moi » – l’utilisateur doit s’être connecté explicitement depuis la dernière connexion complète. Utilisé pour protéger les routes sensibles (changement de mot de passe, suppression de compte) afin qu’un cookie remember-me volé ne puisse pas les atteindre.

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

Marque user comme connecté pour request. Stocke l’identifiant utilisateur dans la session et renvoie une réponse de redirection.

user

L’objet utilisateur renvoyé par le user loader. Doit posséder un attribut id.

remember

Si vrai, définit également un cookie _remember de longue durée. Passez True pour les 30 jours par défaut, ou un entier pour le nombre de jours pendant lesquels le cookie doit durer.

redirect_url

Où rediriger après la connexion. Remplacé par ?next=<url> de la requête d’origine s’il pointe vers un chemin same-site.

Renvoie la réponse de redirection – renvoyez sa valeur depuis le gestionnaire de la route de connexion.

async logout_user(request)

Efface l’identifiant utilisateur de la session et supprime tout cookie _remember. À utiliser depuis une route /logout

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

Renvoie l’objet utilisateur actuellement connecté (ou None). Mémorisé dans request.g.current_user afin que les appels répétés au sein d’une même requête n’atteignent le loader qu’une seule fois.

Exemple

Un flux de connexion minimal

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('/')

Le cookie _remember est lui-même un JWT signé (à l’aide du secret de la session), de sorte qu’un cookie volé ne peut pas être réutilisé sur une application différente ni après que le secret a été renouvelé.