Google Cloud CDN签名Cookie无效:Firebase生成后请求报403
我正在使用Firebase Cloud Functions为Google Cloud CDN生成签名Cookie,生成函数如下:
function signCookie( urlPrefix, keyName, key, expirationTimeSec, ) { // URL-safe base64 encode the URL prefix const encodedUrlPrefix = Buffer.from(urlPrefix) .toString("base64") .replace(/\+/g, "-") .replace(/\//g, "_"); // Construct the policy string const policy = `URLPrefix=${encodedUrlPrefix}:Expires=${expirationTimeSec}:KeyName=${keyName}`; // Decode the base64 key const keyBytes = Buffer.from(key, "base64"); // Create an HMAC-SHA1 signature const signature = crypto .createHmac("sha1", keyBytes) .update(policy) .digest("base64") .replace(/\+/g, "-") // Make it URL-safe .replace(/\//g, "_"); // Construct the full cookie value return { cookieValue: `${policy}:Signature=${signature}`, expires: new Date(expirationTimeSec * 1000).toUTCString() } }
Cookie已正确下发,在Chrome开发者工具的Application标签中可见,且CDN媒体请求的请求头中已包含该Cookie,但请求仍返回403状态码,Google Cloud控制台日志显示statusDetails为signed_request_invalid_signature。请问这是否是Firebase Functions修改了Cookie导致的问题?或是跨域问题?我的客户端网站部署在subdomain.domain.com,CDN部署在cdn.domain.com。
排查与解决方案
1. 排除Firebase Functions修改Cookie的可能
- 在函数中添加日志,输出生成的完整
cookieValue,再和浏览器Application标签里的Cookie值对比。如果两者完全一致,说明Firebase Functions没有修改Cookie;如果不一致,检查函数返回后的响应头设置逻辑(是否存在额外的转义、截断操作)。
2. 核心排查:签名本身的问题(signed_request_invalid_signature的主要原因)
- URLPrefix编码缺失处理:Google要求URLPrefix使用不带填充字符
=的URL-safe base64编码。你的代码目前只替换了+和/,需要额外去掉末尾的=:const encodedUrlPrefix = Buffer.from(urlPrefix) .toString("base64") .replace(/\+/g, "-") .replace(/\//g, "_") .replace(/=+$/, ""); // 新增:移除末尾的填充= - 时间戳验证:确认
expirationTimeSec是秒级Unix时间戳,且当前时间早于该时间戳(Cookie未过期)。如果误用毫秒级时间戳,会导致Expires值无效。 - 密钥与密钥名匹配:确保函数中使用的
key是GCP控制台生成签名密钥时的base64格式私钥,且keyName与控制台内的密钥名称完全一致(大小写敏感)。 - Policy字符串格式:检查Policy字段间的分隔符是英文冒号
:,无多余空格。例如URLPrefix=xxx:Expires=xxx:KeyName=xxx,字段间不能存在空格。 - 签名算法匹配:GCP控制台的签名密钥算法需与代码一致。如果控制台用的是SHA256,需将代码中的
createHmac("sha1", keyBytes)改为createHmac("sha256", keyBytes)。
3. 跨域相关排查(虽请求已带Cookie,但仍需确认)
- Cookie的Domain设置:客户端部署在
subdomain.domain.com,CDN在cdn.domain.com,需将Cookie的Domain设为.domain.com(开头的点不可省略),确保两个子域名都能携带该Cookie。 - SameSite属性:若Cookie的SameSite设为
Strict,跨域请求不会携带;需设为Lax或None(配合Secure属性)才能支持跨域携带。
内容的提问来源于stack exchange,提问作者Dominic Andrews
相关产品推荐
相关产品推荐

