企业微信 webhook 必须用环境变量安全传入带 key 的 url,发送时需严格校验 json 字段、处理超时与错误响应,并对敏感信息脱敏。

Webhook URL 必须带 token 参数且不能泄露
企业微信 Webhook 的 URL 形如 https://qyapi.weixin.qq.com/robot/send?key=xxx,其中 key 是机器人密钥(不是 access_token),它等价于 token。这个 URL 一旦泄露,任何人拿去就能发消息,所以绝不能硬编码在脚本里或提交到 Git。
实操建议:
- 用环境变量传入:
os.getenv("WECHAT_WEBHOOK_URL"),启动时通过WECHAT_WEBHOOK_URL="https://..." python alert.py注入 - 若用 systemd 或 Docker,把 URL 放进 secret 或 env_file,禁止出现在进程命令行(
ps aux可见) - 测试时先发一条到测试群,确认格式和权限正常;正式环境建议加签名验证(需启用「加签」模式,此时 URL 不带 key,要额外算
sign和timestamp)
发送 JSON 要严格符合企业微信文档字段要求
企业微信对 msgtype 和对应内容结构校验很严,错一个字段名或类型(比如把 text 写成 content)就会返回 {"errcode":40071,"errmsg":"invalid msgtype"}。
最常用的是 text 和 markdown 类型,注意:
-
text类型必须带"content"字段(不是"text"),值为字符串,换行用\n -
markdown类型必须带"content"字段,内容支持有限 Markdown(不支持表格、HTML 标签),标题用###,加粗用**text** - 所有请求必须是 POST,
Content-Type: application/json; charset=utf-8,否则返回415 Unsupported Media Type
示例(发送 markdown 报警):
import json
import requests
import os
<p>url = os.getenv("WECHAT_WEBHOOK_URL")
payload = {
"msgtype": "markdown",
"markdown": {
"content": "### [CRITICAL] 服务器 CPU 使用率超 95%\n- 主机:web-prod-01\n- 时间:<font color='\"warning\"'>2024-06-12 14:23:01</font>\n- 当前值:<font color='\"red\"'>97.3%</font>"
}
}
requests.post(url, json=payload, timeout=5)
</p>
超时和网络失败必须主动处理,不能静默丢弃
Webhook 请求可能因 DNS 失败、连接超时、企业微信限流(每分钟最多 20 条)或返回非 200 状态码而失败。如果报警脚本不检查响应,等于没发。
关键检查点:
- 捕获
requests.exceptions.RequestException(涵盖连接、超时、DNS 等) - 检查响应状态码是否为
200,否则读取resp.json().get("errcode") -
errcode == 0才表示成功;errcode == 40014表示 key 错误,errcode == 45009表示超过频率限制 - 失败时建议记录日志并 fallback 到本地文件或邮件(别只 print)
敏感信息脱敏再发送,避免泄露账号密码或 IP
报警内容常含主机名、端口、错误堆栈、数据库连接串等,直接发到群里有安全风险。企业微信不提供服务端脱敏能力,必须在 Python 侧处理。
简单但有效的做法:
- 用正则替换常见敏感模式:
re.sub(r"password=\S+", "password=***", msg)、re.sub(r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b", "xxx.xxx.xxx.xxx", msg) - 对堆栈中的绝对路径做裁剪:
os.path.basename()或只保留最后两级目录 - 避免在
markdown中使用三重反引号包裹原始报错(容易带出完整命令行参数),改用缩进或强调格式
真正难的不是调通接口,而是让每次报警既清晰可读,又不成为攻击者的线索——这需要根据你自己的日志结构写定制化清洗逻辑,没法通用。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











