litefs.auth.middleware 源代码

#!/usr/bin/env python
# coding: utf-8

"""
认证中间件

提供 JWT Token 验证和用户身份注入功能。
"""

import functools
from typing import Callable, Optional


[文档] class AuthMiddleware: """认证中间件""" def __init__( self, app=None, jwt_manager=None, token_location: str = 'header', token_name: str = 'Authorization', token_prefix: str = 'Bearer', exempt_paths: list = None, ): """ 初始化认证中间件 Args: app: Litefs 应用实例(可选) jwt_manager: JWT 管理器 token_location: Token 位置 ('header', 'cookie', 'query') token_name: Token 名称 token_prefix: Token 前缀 exempt_paths: 豁免路径列表 """ self.app = app self.jwt_manager = jwt_manager self.token_location = token_location self.token_name = token_name self.token_prefix = token_prefix self.exempt_paths = exempt_paths or []
[文档] def process_request(self, request): """ 处理请求 Args: request: 请求对象 Returns: None 或响应 """ from .models import get_user_store path = getattr(request, 'path', '/') for exempt_path in self.exempt_paths: if path.startswith(exempt_path): return None token = self._extract_token(request) if not token: return None if not self.jwt_manager: return None payload = self.jwt_manager.decode_token(token) if not payload: return None user_id = payload.get('sub') if not user_id: return None user = get_user_store().get_by_id(user_id) if user: request.user = user request.user_id = user_id return None
[文档] def process_response(self, request, response): """ 处理响应 Args: request: 请求对象 response: 响应数据 Returns: 响应数据 """ return response
def _extract_token(self, request) -> Optional[str]: """ 提取 Token Args: request: 请求对象 Returns: Token 或 None """ if self.token_location == 'header': environ = getattr(request, '_environ', {}) header_key = f'HTTP_{self.token_name.upper().replace("-", "_")}' auth_header = environ.get(header_key, '') if auth_header.startswith(self.token_prefix + ' '): return auth_header[len(self.token_prefix) + 1:] return auth_header or None elif self.token_location == 'cookie': cookies = getattr(request, 'cookies', {}) return cookies.get(self.token_name) elif self.token_location == 'query': query = getattr(request, 'query', {}) return query.get(self.token_name) return None
[文档] def login_required(func: Callable) -> Callable: """ 登录验证装饰器 Args: func: 处理函数 Returns: 装饰后的函数 """ @functools.wraps(func) def wrapper(request, *args, **kwargs): if not hasattr(request, 'user') or request.user is None: return {'error': '需要登录'}, 401 return func(request, *args, **kwargs) return wrapper
[文档] def role_required(*roles: str) -> Callable: """ 角色验证装饰器 Args: *roles: 允许的角色列表 Returns: 装饰器函数 """ def decorator(func: Callable) -> Callable: @functools.wraps(func) def wrapper(request, *args, **kwargs): if not hasattr(request, 'user') or request.user is None: return {'error': '需要登录'}, 401 user_roles = getattr(request.user, 'roles', []) user_role_names = [r.name if hasattr(r, 'name') else str(r) for r in user_roles] for role in roles: if role in user_role_names: return func(request, *args, **kwargs) return {'error': '权限不足'}, 403 return wrapper return decorator