microdot.login --- Luồng đăng nhập người dùng

Một lớp bọc cấp cao hơn xung quanh microdot.session thực hiện luồng đăng nhập bằng tên người dùng / mật khẩu thông thường: một hàm gọi lại user loader ánh xạ user-id được lưu trong session trở lại đối tượng người dùng của ứng dụng, các decorator route chuyển hướng các yêu cầu chưa được xác thực đến URL đăng nhập có thể cấu hình, và các cookie "ghi nhớ tôi" tùy chọn cho phép khách quay lại duy trì đăng nhập qua các phiên trình duyệt.

Yêu cầu microdot.session phải được khởi tạo trên ứng dụng trước khi đối tượng login được tạo -- session là nơi user-id được lưu trữ.

class Login

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

URL mà decorator chuyển hướng các yêu cầu chưa được xác thực đến. Ứng dụng cung cấp form/handler đăng nhập thực tế tại route này. Mặc định là '/login'.

user_loader(f)

Decorator đăng ký hàm gọi lại giải quyết người dùng. f nhận user-id được lưu trong session và trả về đối tượng người dùng (hoặc None nếu id không còn hợp lệ -- một tài khoản đã bị xóa, một session bị thu hồi, v.v.).

login = Login()

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

Trang trí một route bằng phiên bản Login để đặt nó sau xác thực:

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

Các yêu cầu chưa xác thực được chuyển hướng đến login_url với tham số truy vấn ?next=<original-url> để handler đăng nhập có thể đưa người dùng trở lại nơi họ đã đến.

fresh(f)

Tương tự __call__(), nhưng từ chối các session được khôi phục từ cookie "ghi nhớ tôi" -- người dùng phải đã đăng nhập một cách rõ ràng kể từ lần đăng nhập đầy đủ cuối cùng. Dùng để bảo vệ các route nhạy cảm (đổi mật khẩu, xóa tài khoản) để một cookie remember-me bị đánh cắp không thể tiếp cận chúng.

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

Đánh dấu user là đã đăng nhập cho request. Lưu user id vào session và trả về phản hồi chuyển hướng.

user

Đối tượng người dùng được trả về bởi user loader. Phải có thuộc tính id.

remember

Nếu là truthy, cũng đặt một cookie _remember tồn tại lâu dài. Truyền True cho 30 ngày mặc định, hoặc một số nguyên cho số ngày cookie sẽ tồn tại.

redirect_url

Nơi chuyển hướng sau khi đăng nhập. Bị ghi đè bởi ?next=<url> từ yêu cầu gốc nếu nó trỏ đến một đường dẫn cùng site.

Trả về phản hồi chuyển hướng -- trả về giá trị của nó từ handler route đăng nhập.

async logout_user(request)

Xóa user id khỏi session và loại bỏ bất kỳ cookie _remember nào. Sử dụng từ route /logout

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

Trả về đối tượng người dùng hiện đang đăng nhập (hoặc None). Được ghi nhớ trong request.g.current_user để các lần gọi lặp lại trong cùng một yêu cầu chỉ truy cập loader một lần.

Ví dụ

Một luồng đăng nhập tối giản:

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 tự nó là một JWT được ký (sử dụng secret của session), vì vậy một cookie bị đánh cắp không thể được tái sử dụng trên một ứng dụng khác hoặc sau khi secret đã được xoay vòng.