百度API签名验证失败主因是签名逻辑错误:必须用HMAC-SHA256算法,密钥为ak+sk拼接,参数需ksort字典序排序并urlencode(空格转%20),canonical字符串严格按文档拼接,时间戳偏差不得超过180秒,Symfony2加密组件不参与此流程。

百度API签名验证失败,和 Symfony2 自带的加密组件基本无关——它不参与 API 签名流程。问题几乎全出在你自己写的签名生成逻辑里:参数排序错、编码没统一、密钥拼接方式不对、时间戳偏差超 180 秒,或者根本没按百度文档要求用 HMAC-SHA256。
百度签名必须用 HMAC-SHA256,别碰 md5 或 sha1
百度开放平台明确要求所有 API 请求签名使用 HMAC-SHA256 算法,且密钥是 ak + sk 拼接(不是 Base64 解码后的二进制密钥,也不是只用 sk)。用错算法会直接返回 invalid_signature 或 sign_error。
- 错误写法:
hash_hmac('md5', $data, $sk)或hash('sha1', $ak.$sk.$data) - 正确写法:
hash_hmac('sha256', $canonical_string, $ak . $sk),其中$canonical_string是按字典序排序、URL 编码、拼接成的规范字符串 - 注意:PHP 的
hash_hmac()默认输出十六进制字符串,别误用raw_output=true得到二进制——百度验签只认 hex 格式
参数排序和编码必须严格按文档来
百度签名对参数顺序极其敏感:不是按你传参顺序,而是对所有请求参数(除 sign 外)做 ksort() 字典升序,再对 key 和 value 分别做 urlencode(),最后用 & 拼接。漏掉任意一步,哈希值就完全不一样。
调用百度PaddleOCR‑VL大模型API,支持PDF、Word、PPT、图片等多格式文档解析,精准识别印刷体、手写体、表格、公式、图表、印章等复杂元素,支持100+语言,可处理不规则布局和跨页长文档。触发词:文档解析、VLM解析、大模型OCR、PaddleOCR、多模态文档、手写识别、公式识别、复杂版面。
- 常见坑:中文参数没 urlencode;
timestamp值用了毫秒而非秒级 Unix 时间戳;ak被当成普通参数参与排序(其实不该——它只用于拼密钥,不参与 canonical string) - 调试建议:把生成的
$canonical_string打印出来,和百度官方签名工具(或 Postman 插件)输出的逐字符比对,差一个空格或编码差异都会失败 - 特别注意:
urlencode()在 PHP 中对空格编码为+,但百度要求编码为%20,得手动替换:str_replace('+', '%20', urlencode($s))
Symfony2 的 Security Component 不该被卷入 API 签名
有人试图用 security.password_encoder 或 security.encoder_factory 去“加密”签名字段,这是方向性错误。Symfony2 的密码编码器专为用户密码设计(如 BCrypt、PBKDF2),目标是慢、抗爆破、加盐;而 API 签名是确定性、高速、无盐、可逆验证的 MAC 计算。
- 别在
services.yml里配bcrypt编码器去处理sign字段 - 别用
EncoderFactoryInterface::getEncoder()对签名字符串二次哈希 - 如果你在 Controller 里调了
$this->get('security.encoder_factory')->getEncoder(),立刻删掉——它和百度签名毫无关系
时间戳偏差超过 180 秒会直接拒签
百度服务端校验 timestamp 参数与服务器时间差,允许误差 ≤ 180 秒。本地时间不准、容器时区未同步、CI 环境虚拟机休眠后唤醒,都可能导致这个值失效。
- 检查方式:
date -R(Linux)或php -r "echo date(DATE_RFC2822);",对比百度响应头里的Date字段 - 修复建议:容器内加
docker run --network=host或启用 NTP 同步;PHP-FPM 容器中运行ntpd -q -n -p pool.ntp.org - 临时绕过(仅调试):把
timestamp改成当前秒级时间戳硬编码,确认其他环节是否正常
最常被忽略的是:百度签名不接受任何额外 header(比如 X-Requested-With)、不校验 body 内容(除非接口明确要求 sign_body)、也不读取 Symfony 的 session 或 csrf token。它只认 query 或 form 表单里的那几个字段——把逻辑收窄到这几点,90% 的“验签失败”能当场定位。

















