From 36964d9920a75ef679b735cb9de05d5dcc3ed848 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 25 Jun 2026 10:22:34 +0800 Subject: [PATCH] =?UTF-8?q?feat(wecom):=20=E5=9F=9F=E5=90=8D=E6=A0=B9=20se?= =?UTF-8?q?rve=20=E4=BC=81=E4=B8=9A=E5=BE=AE=E4=BF=A1=E5=8F=AF=E4=BF=A1?= =?UTF-8?q?=E5=9F=9F=E5=90=8D=E6=A0=A1=E9=AA=8C=E6=96=87=E4=BB=B6=20WW=5Fv?= =?UTF-8?q?erify=5F*.txt=20+=20bump=200.26.6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- core/__init__.py | 2 +- web/app.py | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/core/__init__.py b/core/__init__.py index 129738c..bb2f6d7 100644 --- a/core/__init__.py +++ b/core/__init__.py @@ -1,3 +1,3 @@ # zcbot 版本号单一事实源:web/app.py 的 FastAPI version、/healthz 返回、前端展示都引这里。 # 改版本只动这一行。 -__version__ = "0.26.5" +__version__ = "0.26.6" diff --git a/web/app.py b/web/app.py index a75d899..4b5a8df 100644 --- a/web/app.py +++ b/web/app.py @@ -1115,6 +1115,21 @@ def create_app() -> FastAPI: def healthz(): return {"status": "ok", "version": __version__} + @app.get("/WW_verify_{token}.txt", include_in_schema=False) + def wecom_domain_verify(token: str): + """企业微信「网页授权可信域名」归属校验文件(公开,无需登录)。 + 把企业微信下载的 WW_verify_.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"]) def me(user_id: UUID = Depends(require_user)): """当前登录用户身份(JWT → user_id → DB role)。