error_code 110表示access_token无效或过期,120表示token与API Key不匹配;需检查OAuth2.0鉴权流程、缓存隔离、token有效期解析及多Bundle间共享逻辑。

鉴权失败时 error_code 返回 110 或 120 怎么办
这是最常见的百度API鉴权错误:error_code 为 110 表示 access_token 无效或过期,120 表示 access_token 与请求的 ak(API Key)不匹配。Symfony2 项目里常因缓存、多环境配置或 token 复用逻辑出错导致。
实操建议:
- 检查
access_token是否从https://aip.baidubce.com/oauth/2.0/token正确获取,且携带了正确的client_id(即ak)、client_secret(即sk)和grant_type=client_credentials - 确认 Symfony2 中存储
access_token的方式:若用FileCache或 APCu,需确保不同环境(dev/prod)不共用缓存路径,否则 dev 环境生成的 token 可能被 prod 错误读取 - 验证 token 是否已过期——百度返回的
expires_in是秒数(通常为31536000,即 1 年),但部分 SDK 或手写逻辑误当作毫秒处理,导致提前判定失效
Symfony2 中调用百度 API 时 curl_setopt(): SSL certificate problem
本地开发环境(尤其是 Windows + WAMP/MAMP)或旧版 PHP(php )常见此错误,本质是 cURL 无法校验百度 HTTPS 证书链,不是鉴权逻辑问题,但会掩盖真实鉴权响应。
实操建议:
- 不要直接设
CURLOPT_SSL_VERIFYPEER => false(绕过校验),应在php.ini中配置curl.cainfo = "path/to/cacert.pem",推荐用 Mozilla 官方 PEM 文件(如 curl.se/ca/cacert.pem) - 在 Symfony2 的 HTTP 客户端(如
guzzlehttp/guzzle)中显式传入 CA 路径:'verify' => '/absolute/path/to/cacert.pem' - 若用
file_get_contents()+stream_context_create(),需在ssl选项里加'cafile',否则默认忽略系统证书
access_token 在多个 Bundle 间共享时失效频繁
Symfony2 的 Bundle 隔离性容易让人忽略单例生命周期——比如 ABundle 和 BBundle 各自实现了一套 token 获取逻辑,各自缓存、各自刷新,结果互相覆盖或重复请求导致百度限流(error_code: 102)。
百度热榜监控 | Baidu Hot Topics Monitor. 获取百度热搜榜、搜索趋势、关键词热度 | Get Baidu trending searches, trends, keyword popularity. 触发词:百度、热搜、baidu.
实操建议:
- 将 token 获取与刷新封装为独立 Service(如
BaiduTokenManager),通过容器注入,避免各处 new 实例 - 使用 Doctrine Cache 或 Redis 做跨请求 token 存储,键名必须包含
ak哈希值(如baidu:token:md5($ak)),防止不同 AK 混用 - 在 token 刷新前 60 秒主动预刷新(而非等
expires_in到时再取),避免高并发下多个请求同时触发刷新造成冲突
POST 请求体含中文时签名始终不匹配
百度 API 签名算法要求对原始请求参数(包括 POST body)做 UTF-8 编码 + URL 编码 + 字典序拼接。Symfony2 默认用 json_encode() 或 http_build_query() 时若未指定 JSON_UNESCAPED_UNICODE,中文会被转成 \uXXXX,导致签名原文与百度服务器计算结果不一致。
实操建议:
- 构造签名原文前,确保所有参数值已用
mb_convert_encoding($value, 'UTF-8', 'auto')统一编码 - 若发送 JSON,用
json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);若发表单,用http_build_query($params, '', '&', PHP_QUERY_RFC3986) - 签名时使用的 secret key 必须是原始
sk(非 Base64 解码后、非 URL 解码后),百度文档里给的sk就是最终密钥字符串
真正卡住的地方往往不是算法本身,而是编码链路里某一处隐式转码——比如 Doctrine Entity 字段用了 utf8mb4_bin 排序却从 DB 读出乱码再参与签名,这种细节在日志里根本不会报错,只会返回 error_code: 282001(签名错误)。

















