- 移除 /api/ 路由的鉴权豁免,所有数据接口必须携带 API Key - 仅 /healthz 和 /admin/(HTML 页面壳)免鉴权 - 前端新增登录遮罩层,401 时弹出 API Key 输入框 - Key 存储在 sessionStorage,所有 API 请求自动附加 X-API-Key header - 支持 ?apiKey=xxx URL 参数自动登录(登录后从 URL 移除避免泄露)
37 lines
1.1 KiB
Python
37 lines
1.1 KiB
Python
"""鉴权中间件:校验请求中的 API Key。"""
|
||
|
||
import uuid
|
||
|
||
from aiohttp import web
|
||
|
||
from .config import WEBHOOK_API_KEY
|
||
from .response import error
|
||
|
||
|
||
@web.middleware
|
||
async def auth_middleware(request: web.Request, handler):
|
||
"""对需要鉴权的路径校验 API Key。仅 /healthz 和管理页面 HTML 无需鉴权。"""
|
||
if request.path == "/healthz" or request.path == "/admin/":
|
||
return await handler(request)
|
||
|
||
auth_header = request.headers.get("Authorization", "")
|
||
if auth_header.startswith("Bearer "):
|
||
key = auth_header[len("Bearer "):]
|
||
else:
|
||
key = request.headers.get("X-API-Key", "")
|
||
|
||
if key != WEBHOOK_API_KEY:
|
||
return error("unauthorized", code=401, status=401)
|
||
|
||
return await handler(request)
|
||
|
||
|
||
@web.middleware
|
||
async def request_id_middleware(request: web.Request, handler):
|
||
"""为每个请求附加唯一 request_id,便于日志追踪。"""
|
||
request_id = request.headers.get("X-Request-ID", uuid.uuid4().hex[:12])
|
||
request["request_id"] = request_id
|
||
response = await handler(request)
|
||
response.headers["X-Request-ID"] = request_id
|
||
return response
|