Files
gate_scout_order/nav_embed.py
T
2026-05-30 15:55:37 +08:00

52 lines
1.7 KiB
Python

"""允许本地导航(LocalNav)iframe 内嵌本服务。环境变量 NAV_ALLOW_EMBED / NAV_EMBED_ORIGINS。"""
from __future__ import annotations
import os
def nav_embed_allowed() -> bool:
return (os.getenv("NAV_ALLOW_EMBED") or "true").strip().lower() in (
"1",
"true",
"yes",
"on",
)
def nav_embed_origins() -> str:
return (os.getenv("NAV_EMBED_ORIGINS") or "*").strip() or "*"
def nav_session_middleware_kwargs() -> dict:
"""
LocalNav 等跨站 iframe 内登录须 SameSite=None + Secure(仅 HTTPS 站点有效)。
NAV_EMBED_SESSION=1 强制开启;auto 时在配置了 NAV_EMBED_ORIGINS 时开启。
"""
raw = (os.getenv("NAV_EMBED_SESSION") or "auto").strip().lower()
if raw in ("0", "false", "no", "off"):
return {"same_site": "lax", "https_only": False}
if raw in ("1", "true", "yes", "on"):
return {"same_site": "none", "https_only": True}
if raw == "auto":
origins = nav_embed_origins()
if origins and origins != "*":
return {"same_site": "none", "https_only": True}
return {"same_site": "lax", "https_only": False}
def install_nav_embed(app) -> None:
if not nav_embed_allowed():
return
origins = nav_embed_origins()
@app.middleware("http")
async def _nav_embed_frame_headers(request, call_next):
response = await call_next(request)
if origins == "*":
response.headers["Content-Security-Policy"] = "frame-ancestors *"
else:
parts = " ".join(o.strip() for o in origins.split(",") if o.strip())
response.headers["Content-Security-Policy"] = f"frame-ancestors 'self' {parts}"
return response