microdot.login — процесс входа пользователя¶
Высокоуровневая обёртка над microdot.session, реализующая привычный процесс входа по имени пользователя и паролю: функция обратного вызова user loader сопоставляет сохранённый в сессии идентификатор пользователя с объектом пользователя приложения, декораторы маршрутов перенаправляют неаутентифицированные запросы на настраиваемый URL входа, а необязательные файлы cookie «запомнить меня» позволяют вернувшимся посетителям оставаться авторизованными между сеансами браузера.
Требует, чтобы microdot.session был инициализирован в приложении до создания объекта входа – именно в сессии хранится идентификатор пользователя.
class Login¶
- class microdot.login.Login(login_url: str = '/login')¶
- login_url
URL, на который декоратор перенаправляет неаутентифицированные запросы. Приложение предоставляет фактическую форму/обработчик входа по этому маршруту. По умолчанию
'/login'.
- user_loader(f)¶
Декоратор, регистрирующий функцию обратного вызова разрешения пользователя. 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>, чтобы обработчик входа мог вернуть пользователя туда, откуда он пришёл.
- fresh(f)¶
Аналогично
__call__(), но отклоняет сессии, восстановленные из файла cookie «запомнить меня» – пользователь должен был явно войти после последнего полного входа. Используется для ограничения доступа к чувствительным маршрутам (смена пароля, удаление учётной записи), чтобы украденный cookie «запомнить меня» не мог до них добраться.
- async login_user(request, user, remember: bool | int = False, redirect_url: str = '/')¶
Отмечает user как вошедшего в систему для request. Сохраняет идентификатор пользователя в сессии и возвращает ответ-перенаправление.
- user
Объект пользователя, возвращённый функцией user loader. Должен иметь атрибут
id.- remember
Если истинно, также устанавливает долгоживущий файл cookie
_remember. ПередайтеTrueдля значения по умолчанию в 30 дней или целое число для количества дней, в течение которых cookie должен сохраняться.- redirect_url
Куда перенаправить после входа. Переопределяется параметром
?next=<url>из исходного запроса, если он указывает на путь того же сайта.
Возвращает ответ-перенаправление – верните его значение из обработчика маршрута входа.
- 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, поэтому повторные вызовы в рамках одного запроса обращаются к загрузчику только один раз.
Пример¶
Минимальный процесс входа:
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 нельзя повторно использовать в другом приложении или после ротации секрета.