microdot.auth --- HTTP 身份验证

用于将路由置于 HTTP 身份验证保护之后的装饰器。提供两种类型:用于浏览器原生弹出提示的 Authorization: Basic <base64> 方案的 BasicAuth,以及用于 API 所使用的 Authorization: Bearer <token> 方案的 TokenAuth

这两个类都派生自一个共同的 BaseAuth 基类;应用程序构造身份验证对象,通过 authenticate() 注册一个身份验证回调,然后用该身份验证实例装饰受保护的路由。

class BasicAuth

class microdot.auth.BasicAuth(realm: str = 'Please login', charset: str = 'UTF-8', scheme: str = 'Basic', error_status: int = 401)

HTTP 基本身份验证。当未经身份验证的请求访问受保护的路由时,浏览器会弹出用户名/密码对话框,并在后续请求中发送 Authorization: Basic <base64(user:pass)>

realm

浏览器在提示旁显示的领域字符串。

charset

WWW-Authenticate 质询中声明的字符集。

scheme

身份验证方案名称。默认为 'Basic'

error_status

身份验证失败时返回的 HTTP 状态码。默认为 401。

authenticate(f)

用于注册凭据检查的装饰器。f 接收 (request, username, password) 并返回已通过身份验证的用户对象(凭据错误时返回 None)。返回的对象存储在 request.g.current_user 上。

basic = BasicAuth(realm='Camera')

@basic.authenticate
async def check(request, username, password):
    user = users.get(username)
    if user and user.check_password(password):
        return user
__call__(f)

BasicAuth 实例装饰一个路由即可对其进行保护:

@app.route('/admin')
@basic
def admin(request):
    return 'hello ' + request.g.current_user.name
optional(f)

__call__() 类似,但不拒绝缺少凭据的请求——处理程序仍会运行,request.g.current_user 被设置为已通过身份验证的用户或 None

class TokenAuth

class microdot.auth.TokenAuth(header: str = 'Authorization', scheme: str = 'Bearer', error_status: int = 401)

Bearer 令牌身份验证。客户端在 Authorization 标头中发送令牌;应用程序根据其所选的任意后端存储来验证该令牌。

header

携带令牌的标头名称。默认值 'Authorization' 期望取值为 Bearer <token>;自定义标头则直接携带令牌值。

scheme

Authorization 标头的身份验证方案。默认为 'Bearer'

error_status

身份验证失败时的 HTTP 状态码。默认为 401。

authenticate(f)

用于注册令牌检查的装饰器。f 接收 (request, token) 并返回用户对象或 None:

import jwt

tokens = TokenAuth()

@tokens.authenticate
async def check(request, token):
    try:
        claims = jwt.decode(token, SECRET)
    except jwt.exceptions.PyJWTError:
        return None
    return claims['sub']
errorhandler(f)

用于覆盖默认 401 响应的装饰器。f 接收请求对象并返回响应(或中止请求)。

__call__(f: Callable) Callable

TokenAuth 实例装饰一个路由即可对其进行保护。没有有效令牌的请求将被拒绝(默认为 401,或由 errorhandler() 返回的任意值)。验证成功后,已通过身份验证的用户位于 request.g.current_user 上:

@app.get('/api/me')
@tokens
async def me(request):
    return {'user': request.g.current_user}

返回包装后的处理程序。

optional(f: Callable) Callable

__call__() 类似,但不拒绝缺少令牌的请求——处理程序仍会运行,request.g.current_user 被设置为已通过身份验证的用户或 None。这对于那些根据调用方是否已通过身份验证而改变输出、但又不强制要求验证的路由很有用:

@app.get('/api/feed')
@tokens.optional
async def feed(request):
    if request.g.current_user:
        return personalized_feed(request.g.current_user)
    return public_feed()

返回包装后的处理程序。

class BaseAuth

class microdot.auth.BaseAuth

BasicAuthTokenAuth 的公共基类。自定义身份验证方案可以对其进行子类化。

auth_callback: Callable | None

通过 authenticate 注册的回调。在应用程序注册该回调之前为 None(用 @auth.authenticate 装饰一个函数即可设置它)。

error_callback: Callable

返回身份验证失败时所发送响应的异步可调用对象。由构造函数设置为返回 401 响应的默认值;可通过 TokenAuth 上的 errorhandler 替换它,或在自定义的 BaseAuth 子类上直接替换。

被装饰的路由会使其 request.g.current_user 被身份验证回调返回的值填充。在路由内部检查该属性即可识别调用方。