microdot.login — przepływ logowania użytkownika¶
Wyższego poziomu nakładka na microdot.session, która implementuje konwencjonalny przepływ logowania za pomocą nazwy użytkownika / hasła: wywołanie zwrotne user loader mapuje przechowywany w sesji identyfikator użytkownika z powrotem na obiekt użytkownika aplikacji, dekoratory tras przekierowują nieuwierzytelnione żądania na konfigurowalny adres URL logowania, a opcjonalne pliki cookie „zapamiętaj mnie” pozwalają powracającym odwiedzającym pozostać zalogowanymi między sesjami przeglądarki.
Wymaga zainicjowania microdot.session w aplikacji przed skonstruowaniem obiektu logowania – sesja jest miejscem, w którym przechowywany jest identyfikator użytkownika.
class Login¶
- class microdot.login.Login(login_url: str = '/login')¶
- login_url
Adres URL, na który dekorator przekierowuje nieuwierzytelnione żądania. Aplikacja udostępnia właściwy formularz/procedurę obsługi logowania na tej trasie. Domyślnie
'/login'.
- user_loader(f)¶
Dekorator rejestrujący wywołanie zwrotne rozpoznające użytkownika. f przyjmuje identyfikator użytkownika przechowywany w sesji i zwraca obiekt użytkownika (lub
None, jeśli identyfikator nie jest już prawidłowy – usunięte konto, unieważniona sesja itp.).login = Login() @login.user_loader async def load_user(user_id): return users.get(user_id)
- __call__(f)¶
Udekorowanie trasy instancją
Loginchroni ją za uwierzytelnianiem:@app.get('/dashboard') @login async def dashboard(request): user = request.g.current_user # ...
Nieuwierzytelnione żądania są przekierowywane na login_url z parametrem zapytania
?next=<original-url>, aby procedura obsługi logowania mogła odesłać użytkownika tam, skąd przyszedł.
- fresh(f)¶
Podobnie jak
__call__(), ale odrzuca sesje przywrócone z pliku cookie „zapamiętaj mnie” – użytkownik musiał zalogować się jawnie od ostatniego pełnego logowania. Używane do ochrony wrażliwych tras (zmiana hasła, usunięcie konta), aby skradziony plik cookie zapamiętania nie mógł do nich dotrzeć.
- async login_user(request, user, remember: bool | int = False, redirect_url: str = '/')¶
Oznacza użytkownika user jako zalogowanego dla request. Przechowuje identyfikator użytkownika w sesji i zwraca odpowiedź przekierowania.
- user
Obiekt użytkownika zwrócony przez user loader. Musi mieć atrybut
id.- remember
Jeśli prawdziwe, ustawia również długotrwały plik cookie
_remember. PrzekażTruedla domyślnych 30 dni lub liczbę całkowitą określającą liczbę dni, przez które plik cookie ma obowiązywać.- redirect_url
Dokąd przekierować po zalogowaniu. Nadpisywane przez
?next=<url>z pierwotnego żądania, jeśli wskazuje na ścieżkę z tej samej witryny.
Zwraca odpowiedź przekierowania – zwróć jej wartość z procedury obsługi trasy logowania.
- async logout_user(request)¶
Usuwa identyfikator użytkownika z sesji i usuwa wszelkie pliki cookie
_remember. Użyj z trasy/logout@app.post('/logout') async def logout(request): await login.logout_user(request) return redirect('/')
- async get_current_user(request)¶
Zwraca obiekt aktualnie zalogowanego użytkownika (lub
None). Memoizowany wrequest.g.current_user, więc powtarzane wywołania w obrębie jednego żądania trafiają do loadera tylko raz.
Przykład¶
Minimalny przepływ logowania:
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('/')
Plik cookie _remember sam jest podpisanym JWT (z użyciem sekretu sesji), więc skradziony plik cookie nie może zostać ponownie użyty w innej aplikacji ani po rotacji sekretu.