feat(wecom): 域名根 serve 企业微信可信域名校验文件 WW_verify_*.txt + bump 0.26.6

GET /WW_verify_{token}.txt 从 ZCBOT_WECOM_VERIFY_DIR(默 repo 根)读同名文件返回,
公开端点 + token isalnum 防穿越。解企业微信「网页授权可信域名」归属校验
(zcbot 根路径原是 302 跳 SPA,验证文件 404)。配好可信域名才能配可信IP(修推送 60020)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
caoqianming 2026-06-25 10:22:34 +08:00
parent ed2ff52bf4
commit 36964d9920
2 changed files with 16 additions and 1 deletions

View File

@ -1,3 +1,3 @@
# zcbot 版本号单一事实源:web/app.py 的 FastAPI version、/healthz 返回、前端展示都引这里。 # zcbot 版本号单一事实源:web/app.py 的 FastAPI version、/healthz 返回、前端展示都引这里。
# 改版本只动这一行。 # 改版本只动这一行。
__version__ = "0.26.5" __version__ = "0.26.6"

View File

@ -1115,6 +1115,21 @@ def create_app() -> FastAPI:
def healthz(): def healthz():
return {"status": "ok", "version": __version__} return {"status": "ok", "version": __version__}
@app.get("/WW_verify_{token}.txt", include_in_schema=False)
def wecom_domain_verify(token: str):
"""企业微信「网页授权可信域名」归属校验文件(公开,无需登录)。
把企业微信下载的 WW_verify_<token>.txt 放到 ZCBOT_WECOM_VERIFY_DIR
(默认 repo ),本路由按文件名在域名根 serve"""
from fastapi.responses import PlainTextResponse
from core.paths import ROOT
if not token.isalnum(): # 防路径穿越
raise HTTPException(404, "not found")
vdir = Path(os.getenv("ZCBOT_WECOM_VERIFY_DIR", "").strip() or str(ROOT))
fpath = vdir / f"WW_verify_{token}.txt"
if not fpath.is_file():
raise HTTPException(404, "verify file not found")
return PlainTextResponse(fpath.read_text(encoding="utf-8"))
@app.get("/v1/me", tags=["misc"]) @app.get("/v1/me", tags=["misc"])
def me(user_id: UUID = Depends(require_user)): def me(user_id: UUID = Depends(require_user)):
"""当前登录用户身份(JWT → user_id → DB role)。 """当前登录用户身份(JWT → user_id → DB role)。