Files
aiagent/backend/app/core/security_headers.py

46 lines
1.8 KiB
Python
Raw Normal View History

"""安全响应头中间件 — HSTS / X-Frame-Options / X-Content-Type-Options 等。"""
from __future__ import annotations
from fastapi import Request, Response
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.types import ASGIApp
from app.core.config import settings
class SecurityHeadersMiddleware(BaseHTTPMiddleware):
"""为 HTTP 响应注入安全加固头。
- Strict-Transport-Security (HSTS)仅在 HTTPS 且启用时注入
- X-Content-Type-Options: nosniff
- X-Frame-Options: DENY
- X-XSS-Protection: 1; mode=block
- Referrer-Policy: strict-origin-when-cross-origin
- Permissions-Policy: 限制敏感 API摄像头/麦克风/定位
"""
def __init__(self, app: ASGIApp) -> None:
super().__init__(app)
async def dispatch(self, request: Request, call_next) -> Response:
response = await call_next(request)
# HSTS仅在 HTTPS 且显式启用时注入(开发环境 http 不应发送 HSTS
if settings.HSTS_ENABLED and request.url.scheme == "https":
hsts = f"max-age={settings.HSTS_MAX_AGE}"
if settings.HSTS_INCLUDE_SUBDOMAINS:
hsts += "; includeSubDomains"
response.headers["Strict-Transport-Security"] = hsts
# 通用安全头(对所有响应安全)
response.headers.setdefault("X-Content-Type-Options", "nosniff")
response.headers.setdefault("X-Frame-Options", "DENY")
response.headers.setdefault("X-XSS-Protection", "1; mode=block")
response.headers.setdefault("Referrer-Policy", "strict-origin-when-cross-origin")
response.headers.setdefault(
"Permissions-Policy",
"camera=(), microphone=(), geolocation=()",
)
return response