使用 Python 请求钉钉机器人接口返回 401 unauthorized 怎么办

文章导读
遇到 401 错误,通常是因为钉钉机器人的安全设置(签名、关键词或 IP 白名单)与请求参数不匹配,或者 Webhook 地址本身已失效。
📋 目录
  1. 快速处理思路
  2. 为什么会这样
  3. 分步处理
  4. 怎么验证是否生效
  5. 常见坑
  6. 参考来源
A A

遇到 401 错误,通常是因为钉钉机器人的安全设置(签名、关键词或 IP 白名单)与请求参数不匹配,或者 Webhook 地址本身已失效。

先说结论:优先检查机器人后台的安全设置类型,确保 Python 代码中携带了正确的签名参数或关键词。

  • 先确认:登录钉钉管理后台,查看机器人安全设置是关键词、签名还是 IP 白名单。
  • 先处理:根据安全类型修改 Python 请求代码,签名模式需计算 timestamp 和 sign。
  • 再验证:发送测试消息,确认返回 JSON 中 errcode 为 0。

快速处理思路

import requests
import hmac
import hashlib
import base64
import urllib.parse
import time

# 替换为你的实际配置
webhook_url = 'https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN'
secret = 'YOUR_SECRET'

# 生成签名
timestamp = str(round(time.time() * 1000))
secret_enc = secret.encode('utf-8')
string_to_sign = '{}\n{}'.format(timestamp, secret)
string_to_sign_enc = string_to_sign.encode('utf-8')
hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()
sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))

# 拼接完整 URL
url = '{}×tamp={}&sign={}'.format(webhook_url, timestamp, sign)

# 发送请求
headers = {'Content-Type': 'application/json'}
data = {'msgtype': 'text', 'text': {'content': '测试消息'}}
response = requests.post(url, json=data, headers=headers)
print(response.text)

为什么会这样

HTTP 状态码 401 代表未经授权。在钉钉机器人场景中,这通常不是指账号密码错误,而是指 webhook 请求未通过安全校验。钉钉自定义机器人支持三种安全设置:自定义关键词、IP 地址白名单、签名校验。

如果后台开启了签名校验,而请求 URL 中缺少 timestamp 和 sign 参数,或者计算错误,服务端会直接拒绝请求。此外,如果请求头 Content-Type 不是 application/json,或者机器人已被禁用,也可能导致类似授权失败的响应。

分步处理

1. 核对安全设置
登录钉钉管理后台,进入机器人配置页面。确认当前启用的安全方式。如果是关键词,消息内容必须包含该词;如果是签名,必须按算法生成参数。

2. 检查代码实现
确保使用 HMAC-SHA256 算法。注意 timestamp 单位是毫秒。secret 必须与后台显示完全一致,不要多复制空格。

使用 Python 请求钉钉机器人接口返回 401 unauthorized 怎么办

3. 确认请求头
使用 Python requests 库时,json 参数会自动设置 Content-Type,但手动构造 body 时需显式添加 headers={'Content-Type': 'application/json'}。

4. 检查机器人状态
确认机器人未被管理员禁用或删除。如果 webhook 地址中的 access_token 已变更,需重新复制新地址。

怎么验证是否生效

运行代码后,观察响应内容。钉钉接口通常返回 HTTP 200,但业务状态在 JSON body 中。

成功标志:返回 JSON 中包含 "errcode": 0"errmsg": "ok"

使用 Python 请求钉钉机器人接口返回 401 unauthorized 怎么办

失败标志:如果仍然返回 401 或 JSON 中 errcode 非 0,查看 errmsg 提示。常见提示包括“签名无效”、“关键词不匹配”等。

常见坑

1. 时间戳单位错误
钉钉要求毫秒级时间戳,Python 中 time.time() 是秒,需乘以 1000 并取整。

2. 换行符差异
签名字符串拼接时,timestamp 和 secret 之间必须是换行符 \n,不能是空格或其他字符。

3. URL 编码问题
计算出的 sign 包含特殊字符,必须进行 URL encode(如 quote_plus),否则请求会被拦截。

4. 密钥复制错误
后台显示的 secret 可能包含前后空格,复制时需仔细检查,建议在代码中打印长度核对。

参考来源

  • 钉钉开放平台 - 自定义机器人接入,https://open.dingtalk.com/document/robots/custom-robot-access
  • 钉钉开放平台 - 签名校验算法说明,https://open.dingtalk.com/document/robots/signature-validation