Files
findreve/middleware/dependencies.py
2026-01-12 11:44:55 +08:00

63 lines
1.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from typing import Annotated, TypeAlias
from fastapi import Depends, Request
from sqlmodel.ext.asyncio.session import AsyncSession
from model.database import Database
from model.mixin.table import TableViewRequest
from model import Item
from model.item import ItemTypeEnum
from pkg import utils
SessionDep: TypeAlias = Annotated[AsyncSession, Depends(Database.get_session)]
"""数据库会话依赖,用于路由函数中获取数据库会话"""
# 新增:表格视图请求依赖(用于分页排序)
TableViewRequestDep: TypeAlias = Annotated[TableViewRequest, Depends()]
"""分页排序请求依赖,用于 LIST 端点"""
async def get_device_from_cert(
request: Request,
session: SessionDep,
) -> Item:
"""
从 mTLS 客户端证书中提取设备序列号并验证设备。
客户端证书的 CN (Common Name) 字段应存储设备序列号 (UUID)。
反向代理Nginx/Apache验证证书后通过 HTTP Header 将 CN 传递给 FastAPI。
Nginx 配置示例:
proxy_set_header X-Client-CN $ssl_client_s_dn_cn;
Apache 配置示例:
RequestHeader set X-Client-CN "%{SSL_CLIENT_S_DN_CN}s"
"""
# 从 Header 获取设备序列号(由反向代理注入)
serial_number = request.headers.get("X-Client-CN")
if not serial_number:
utils.raise_unauthorized("Device certificate required")
# 验证 UUID 格式
try:
from uuid import UUID
serial_uuid = UUID(serial_number)
except ValueError:
utils.raise_unauthorized("Invalid device serial number format")
# 查找设备
device = await Item.get(session, Item.id == serial_uuid)
if not device:
utils.raise_not_found("Device not found")
if device.type != ItemTypeEnum.esp32:
utils.raise_forbidden("Not an ESP device")
return device
DeviceDep: TypeAlias = Annotated[Item, Depends(get_device_from_cert)]
"""设备认证依赖,通过 mTLS 证书验证 ESP 设备"""