使用HTML表单上传至Google Cloud Storage遇签名不匹配错误求助
问题分析与解决办法
以下是导致SignatureDoesNotMatch错误的核心原因及对应修复方案:
1. 日期与区域参数不匹配
- 策略文档中
x-goog-date为20191102T043530Z,但生成签名密钥时使用的日期是20221207,两者必须完全对齐(取x-goog-date的前8位作为签名日期)。 - 策略文档中
x-goog-credential的区域是us-central1,但代码里用了asia-south2,区域参数必须和凭证中的一致。
2. crypto-js HMAC参数顺序错误
crypto-js的HmacSHA256方法参数顺序是**(待签名字符串, 密钥)**,你的代码完全搞反了:
- 错误写法:
crypto.HmacSHA256("20221207","GOOG4" + key) - 正确写法:
crypto.HmacSHA256("20191102", "GOOG4" + key)
3. Policy文档Base64编码不规范
直接用btoa(JSON.stringify(...))会因UTF-8字符导致编码异常,需要先将JSON字符串转成UTF-8编码再做Base64处理:
function utf8ToBase64(str) { return btoa(unescape(encodeURIComponent(str))); }
4. 签名输出格式错误
crypto-js的HmacSHA256返回WordArray类型,直接调用toString()会得到十六进制字符串,但GCS要求的是Base64格式的签名,需指定编码格式:
this.signature = MessageDigest.toString(crypto.enc.Base64);
修正后的完整代码示例
const policyDate = "20191102"; // 与策略文档x-goog-date的前8位保持一致 const key = "你的HMAC密钥"; // 正确生成签名密钥 let key_date = crypto.HmacSHA256(policyDate, "GOOG4" + key); let key_region = crypto.HmacSHA256("us-central1", key_date); // 匹配凭证中的区域 let key_service = crypto.HmacSHA256("storage", key_region); let signing_key = crypto.HmacSHA256("goog4_request", key_service); // 正确编码Policy文档 function utf8ToBase64(str) { return btoa(unescape(encodeURIComponent(str))); } let encoded_policy = utf8ToBase64(JSON.stringify(this.PolicyDocument)); // 生成符合要求的签名 let MessageDigest = crypto.HmacSHA256(encoded_policy, signing_key); this.signature = MessageDigest.toString(crypto.enc.Base64);
内容的提问来源于stack exchange,提问作者Abhinay
相关产品推荐
相关产品推荐

