通过Cloud CDN访问GCP存储桶时遇`signed_request_invalid_format`错误
问题背景
使用签名Cookie通过Cloud CDN访问GCP存储桶中的受限文件,已通过自定义函数生成Cookie并发送至CDN,但访问返回403禁止错误,负载均衡日志显示状态详情为signed_request_invalid_format。
签名Cookie生成代码
signCookie(urlPrefix: string, keyName: string, key: string, expires: number) { // Base64url encode the url prefix const urlPrefixEncoded = Buffer.from(urlPrefix).toString('base64url'); // Input to be signed const input = `URLPrefix=${urlPrefixEncoded}:Expires=${expires}:KeyName=${keyName}`; // Create bytes from given key string. const keyBytes = Buffer.from(key, 'base64'); // Use key bytes and crypto.createHmac to produce a base64 encoded signature which is then escaped to be base64url encoded. const signature = createHmac('sha1', keyBytes).update(input).digest('base64url'); // Adding the signature on the end if the cookie value const signedValue = `${input}:Signature=${signature}`; return signedValue; }
错误信息
Error: Forbidden
Your client does not have permission to get URL ********/sample.pdf from this server.
负载均衡日志详情:statusDetails: "signed_request_invalid_format"
排查与修复建议
- 检查URL前缀的Base64url编码:GCP要求编码后必须移除所有填充字符
=,虽然Node.js的toString('base64url')默认会处理,但需确认实际生成的urlPrefixEncoded无多余=,必要时手动去除:const urlPrefixEncoded = Buffer.from(urlPrefix).toString('base64url').replace(/=/g, ''); - 验证签名输入的字段顺序与拼写:GCP严格要求字段顺序为
URLPrefix→Expires→KeyName,且字段名必须完全匹配(注意大写),不能出现拼写错误。 - 确认签名的Base64url编码合规:部分Node.js版本的
base64url编码可能存在差异,可手动实现确保符合GCP标准:const signature = createHmac('sha1', keyBytes) .update(input) .digest('base64') .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/=/g, ''); - 检查Cookie名称:Cloud CDN要求签名Cookie的名称必须是
Cloud-CDN-Cookie,名称错误会直接导致格式无效。 - 验证Expires时间戳:
expires必须是秒级Unix时间戳,如果传入的是毫秒级时间戳,需除以1000取整:const expires = Math.floor(Date.now() / 1000) + 3600; // 示例:1小时后过期 - 确认密钥正确性:确保
key参数是从GCP控制台获取的签名密钥私有密钥(Base64格式),而非公钥或其他格式密钥。
验证步骤
- 打印生成的
signedValue,检查格式是否严格符合URLPrefix=xxx:Expires=xxx:KeyName=xxx:Signature=xxx,无多余空格或特殊字符。 - 使用GCP官方签名工具重新生成签名Cookie,对比自定义函数的生成结果是否一致。
内容的提问来源于stack exchange,提问作者Charchit Kapoor
相关产品推荐
相关产品推荐

