microdot.login --- ユーザーログインフロー

従来のユーザー名/パスワードによるログインフローを実装する、microdot.session 上位のラッパーです。user loader コールバックがセッションに格納されたユーザー ID をアプリケーションのユーザーオブジェクトに対応付け、ルートデコレータが認証されていないリクエストを設定可能なログイン URL にリダイレクトし、オプションの「remember me」クッキーによって再訪したユーザーがブラウザセッションをまたいでサインインを維持できます。

ログインオブジェクトを構築する に、アプリケーション上で microdot.session が初期化されている必要があります。ユーザー ID はセッションに格納されるためです。

class Login

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

デコレータが認証されていないリクエストをリダイレクトする URL。アプリケーションはこのルートに実際のログインフォーム/ハンドラを用意します。デフォルトは '/login' です。

user_loader(f)

ユーザー解決コールバックを登録するデコレータ。f はセッションに格納されたユーザー ID を受け取り、ユーザーオブジェクトを返します(ID がもはや有効でない場合 -- 削除されたアカウント、取り消されたセッションなど -- は 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
    # ...

認証されていないリクエストは、?next=<original-url> クエリパラメータを付けて login_url にリダイレクトされるため、ログインハンドラはユーザーを元の場所に戻すことができます。

fresh(f)

__call__() と同様ですが、「remember me」クッキーから復元されたセッションを拒否します。ユーザーは前回の完全なログイン以降、明示的にログインしている必要があります。盗まれた remember-me クッキーが機密性の高いルート(パスワード変更、アカウント削除)に到達できないようにするために使用します。

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

request に対して user をログイン済みとしてマークします。ユーザー ID をセッションに格納し、リダイレクト応答を返します。

user

ユーザーローダーが返したユーザーオブジェクト。id 属性を持っている必要があります。

remember

真と評価される場合、長期間有効な _remember クッキーも設定します。デフォルトの 30 日には True を、クッキーの有効日数を指定するには整数を渡してください。

redirect_url

ログイン後にリダイレクトする先。元のリクエストの ?next=<url> が同一サイトのパスを指している場合、それによって上書きされます。

リダイレクト応答を返します -- その値をログインルートハンドラから返してください。

async logout_user(request)

セッションからユーザー 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 にメモ化されるため、1 つのリクエスト内で繰り返し呼び出してもローダーは一度しか実行されません。

最小限のログインフロー:

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 であるため、盗まれたクッキーを別のアプリケーションで、またはシークレットがローテーションされた後で再利用することはできません。