microdot.login --- ขั้นตอนการล็อกอินผู้ใช้

เป็น wrapper ระดับสูงกว่าที่ครอบ microdot.session ซึ่งใช้งานขั้นตอนการล็อกอินด้วยชื่อผู้ใช้และรหัสผ่านแบบมาตรฐาน: คอลแบ็ก user loader จะแมป user-id ที่เก็บในเซสชันกลับเป็นออบเจ็กต์ผู้ใช้ของแอปพลิเคชัน ตัวตกแต่งเส้นทางจะเปลี่ยนเส้นทางคำขอที่ยังไม่ได้ยืนยันตัวตนไปยัง URL ล็อกอินที่กำหนดค่าได้ และคุกกี้ "จดจำฉัน" แบบเลือกใช้จะช่วยให้ผู้เยี่ยมชมที่กลับมาไม่ต้องล็อกอินใหม่ข้ามเซสชันเบราว์เซอร์

ต้องการให้ microdot.session ถูกเริ่มต้นบนแอปพลิเคชัน ก่อน สร้างออบเจ็กต์ login -- เซสชันคือที่เก็บ user-id

class Login

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

URL ที่ตัวตกแต่งจะเปลี่ยนเส้นทางคำขอที่ยังไม่ได้ยืนยันตัวตนไปยัง แอปพลิเคชันต้องจัดเตรียมฟอร์ม/ตัวจัดการล็อกอินจริงที่เส้นทางนี้ ค่าเริ่มต้น '/login'

user_loader(f)

ตัวตกแต่งที่ลงทะเบียนคอลแบ็ก user-resolver f รับ user-id ที่เก็บในเซสชันและคืนออบเจ็กต์ผู้ใช้ (หรือ None หาก id ไม่ถูกต้องอีกต่อไป -- บัญชีที่ถูกลบ เซสชันที่ถูกเพิกถอน ฯลฯ)

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__() แต่ปฏิเสธเซสชันที่คืนจากคุกกี้ "จดจำฉัน" -- ผู้ใช้ต้องล็อกอินอย่างชัดเจนตั้งแต่ล็อกอินครั้งล่าสุด ใช้เพื่อคุ้มครองเส้นทางที่ละเอียดอ่อน (เปลี่ยนรหัสผ่าน ลบบัญชี) เพื่อป้องกันไม่ให้คุกกี้ remember-me ที่ถูกขโมยเข้าถึงได้

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

ทำเครื่องหมาย user ว่าล็อกอินแล้วสำหรับ request เก็บ user id ในเซสชันและคืนการตอบกลับแบบเปลี่ยนเส้นทาง

user

ออบเจ็กต์ผู้ใช้ที่คืนโดย user loader ต้องมีแอตทริบิวต์ id

remember

ถ้าเป็นค่า truthy จะตั้งคุกกี้ _remember ที่มีอายุยาวนานด้วย ส่ง True สำหรับค่าเริ่มต้น 30 วัน หรือจำนวนเต็มสำหรับจำนวนวันที่คุกกี้ควรมีอายุ

redirect_url

ที่จะเปลี่ยนเส้นทางหลังล็อกอิน สามารถถูกแทนที่ด้วย ?next=<url> จากคำขอเดิม หากชี้ไปยังพาธบนไซต์เดียวกัน

คืนการตอบกลับแบบเปลี่ยนเส้นทาง -- คืนค่านี้จากตัวจัดการเส้นทางล็อกอิน

async logout_user(request)

ล้าง user id จากเซสชันและลบคุกกี้ _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 เพื่อให้การเรียกซ้ำในคำขอเดียวกันเรียก loader เพียงครั้งเดียว

ตัวอย่าง

ขั้นตอนการล็อกอินขั้นต่ำ:

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

คุกกี้ _remember เองเป็น JWT ที่มีลายเซ็น (โดยใช้ secret ของเซสชัน) ดังนั้นคุกกี้ที่ถูกขโมยจึงไม่สามารถนำไปใช้กับแอปพลิเคชันอื่นหรือหลังจากที่ secret ถูกเปลี่ยนได้