COS q-signature 签名原理:Clara 原生实现的步骤拆解

CLARA轻量论坛系统
CLARA轻量论坛系统 星耀SVIP星耀SVIP管理员管理员 黑卡会员黑卡会员
发布于 2026-09-29 20:01 ·1 浏览 ·0 回复

学完这篇,你能搞清楚腾讯云 COS 的 q-signature 到底由哪几段拼成、每一步用什么算法,以及 Clara 在不装 SDK 的前提下是怎么把这套签名原生实现出来的。

第一步:先看清一张签名的长相

COS 每次请求都要带 `Authorization` 头(或者把签名拼进 URL 做预签名),它的长相是固定的:

q-sign-algorithm=sha1&q-ak=AKIDxxxx&q-sign-time=1700000000;1700000600&q-key-time=1700000000;1700000600&q-header-list=host&q-url-param-list=&q-signature=xxxxxxxx

七个字段里,`q-ak`、`q-sign-time`、`q-key-time`、两个 list 你都能直接写出来,只有 `q-signature` 是需要计算的。

注意:`q-sign-time` 的格式是"起始秒;结束秒",单位是秒。写成毫秒是最常见的翻车点。两个时间通常设成一样,有效期按需给(预签名 URL 建议几分钟)。

第二步:在后台把密钥填好

进入后台「系统设置→云存储」,填好 SecretId、SecretKey、Bucket、Region 和访问域名,然后打开云存储开关。

SecretKey 是唯一的签名原料,只能待在服务端,绝不能下发到浏览器。

第三步:派生 SignKey

COS 不直接用 SecretKey 签名,而是先做一次 HMAC 派生:

SignKey = HMAC-SHA1(SecretKey, q-key-time)   // 取十六进制小写

Clara 不需要 Composer 装 SDK,PHP 内置函数就够:

$signKey = hash_hmac('sha1', $keyTime, $secretKey);

注意:`hash_hmac($algo, $data, $key)` 的参数顺序是「数据在前、密钥在后」,跟直觉反着来,写反了签名永远对不上。

第四步:拼 HttpString

HttpString 是签名的主体,四行内容、三个换行:

HttpString =
    strtolower($method) . "\n" .
    $uriPathname        . "\n" .
    $urlParams          . "\n" .
    $headers            . "\n"
  • `uriPathname`:以 `/` 开头,做 RFC3986 编码。PHP 用 `rawurlencode`,别用 `urlencode`(空格会变成 `+`)
  • `urlParams`:所有 query 参数按 key 字典序排列,key 和 value 都要编码,拼成 `k=v&k=v`;没有就留空
  • `headers`:参与签名的头(至少包含 `host`),key 全部小写并按字典序排,格式 `key=编码后的值`

注意:只把真正参与签名的头写进 `headers` 和 `q-header-list`,两边必须一致。多写一个或少写一个都会签名失败。

第五步:拼 StringToSign

StringToSign = "sha1\n" . $qSignTime . "\n" . sha1($httpString) . "\n"

这里的 `sha1()` 同样取十六进制小写。

第六步:算出 Signature

Signature = HMAC-SHA1(SignKey, StringToSign)   // 十六进制小写
$signature = hash_hmac('sha1', $stringToSign, $signKey);

第七步:拼回 Authorization

把算好的 `q-signature` 填回第一步那个串,放进请求头 `Authorization` 即可。如果要做前端直传,就把它拼成 query 参数,形成一条带有效期的预签名 URL。

第八步:验证与排错

收到 `SignatureDoesNotMatch` 时,按顺序查这五项:

  1. 时间戳是不是秒
  2. URI 是不是 `rawurlencode` 编码过、且以 `/` 开头
  3. header 的 key 是不是全小写并按字典序排
  4. 换行符数量(HttpString 结尾那一个 `\n` 最容易漏)
  5. 服务器时间是否同步(NTP),偏几分钟就可能落在有效期外

注意:最有效的调试手段是把 HttpString 和 StringToSign 原样打印出来看,肉眼扫一遍往往就发现问题了。

第九步:Clara 这边的落地方式

  • 不引 SDK:全程用 PHP 内置的 `hash_hmac` / `sha1` / `rawurlencode`,无 Composer、无编译缓存
  • 配置即生效:后台保存密钥后,下一次上传就用新配置,不需要清缓存
  • 密钥不出服务端:前端拿到的要么是签名后的请求头,要么是短时效的预签名 URL
  • 权限收敛:预签名 URL 的 `q-key-time` 设短一些,过期即失效,避免链接被转发滥用

小结

  • q-signature 的核心就三步 HMAC:派生 SignKey → 签 StringToSign → 得出 Signature
  • 中间那层 HttpString 是"签了哪些东西"的清单,method、路径、参数、header 四段缺一不可
  • 出错九成集中在三处:时间戳单位、URL 编码方式、header 是否小写并排序
  • Clara 靠 PHP 内置函数原生实现,不装 SDK、保存即生效,服务器时间记得同步
本文转载自 Clara轻量论坛系统 - 轻量级 PHP 论坛系统,原文地址:https://www.leleweb.cn/thread-643.html
转载请注明出处,版权归原作者所有。

全部回复 0

还没有回复,来抢沙发~