You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CloudFront签名URL提示无效/未知密钥并返回403错误排查求助

CloudFront签名URL返回403(无效/未知密钥)排查方案

问题背景

我为S3存储桶创建了CloudFront分发,已配置正确的Origin Access Control(OAC)及对应的存储桶策略,将分发的Restrict Viewer Access设置为我的密钥组,且密钥组包含正确的公钥,代码中也使用了正确的私钥路径和密钥对ID。但生成的签名URL提示无效/未知密钥并返回403错误。另外我添加了CORS策略(可能不需要),并确保分发行为包含CORS头、查询字符串,还配置了可能不必要的Cookie。

可能的原因及排查步骤

  • 密钥对不匹配:确认密钥组中的公钥,是否与代码中使用的私钥属于同一对CloudFront专用密钥对(不是IAM用户密钥)。CloudFront密钥对需在AWS账户安全凭证页面生成,而非IAM控制台。
  • 签名算法不兼容:CloudFront要求签名使用SHA-1或SHA-256算法,搭配PKCS#1填充。检查代码签名逻辑是否符合要求,同时确认分发的签名版本设置(默认支持v1/v2,v4需额外配置)。
  • Policy文档格式错误:
    • Resource字段必须与实际请求URL完全一致,包括大小写、路径分隔符、查询参数(若有)。CloudFront对路径大小写敏感,需与S3对象路径严格匹配。
    • EpochTime必须是UTC时间戳,代码中DateTime.UtcNow是正确的,但要确认ToUnixTimeSeconds()返回的秒级时间戳无误。
    • Policy JSON必须是紧凑格式(无多余空格/换行),默认序列化的缩进格式会导致签名哈希不匹配。
  • URL编码不完整:确保Policy的URL转义完全(Uri.EscapeDataString需处理所有特殊字符),签名的Base64转换需正确替换+为-、/为_并移除末尾=。
  • CloudFront配置未生效:
    • 确认Restrict Viewer Access设为Yes且选择了正确的密钥组。
    • 分发行为的Query String Forwarding and Caching需设为All,保证签名参数能被CloudFront接收验证。
    • 配置变更需等待5-15分钟部署生效,未生效前会返回403。
  • 私钥加载异常:检查私钥PEM文件是否完整,必须包含-----BEGIN RSA PRIVATE KEY-----和-----END RSA PRIVATE KEY-----头尾,中间密钥内容格式正确(无多余换行或损坏)。

代码问题修正

你的代码中存在一个关键错误:Newtonsoft.Json默认生成带缩进的JSON Policy,导致签名哈希与CloudFront验证时的哈希值不匹配,触发403。需修改序列化逻辑为紧凑格式:

// 修正Policy序列化代码
string policyJson = JsonConvert.SerializeObject(policy, Formatting.None);

另外,可尝试生成无Policy的签名URL(仅用过期时间)简化排查,验证基础签名逻辑是否正常:

// 无Policy的签名URL生成示例(用于排查)
public static string GenerateSignedUrlWithoutPolicy(string distributionDomain, string filePath, string privateKeyFilePath, string keyPairId, DateTime expirationDate)
{
    string resourcePath = $"/{filePath}";
    long epochTime = ((DateTimeOffset)expirationDate).ToUnixTimeSeconds();
    string signString = $"{epochTime}{resourcePath}";

    string privateKey = File.ReadAllText(privateKeyFilePath);
    using (RSA rsa = RSA.Create())
    {
        rsa.ImportFromPem(privateKey);
        byte[] data = Encoding.UTF8.GetBytes(signString);
        byte[] signature = rsa.SignData(data, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
        string urlSafeSignature = Convert.ToBase64String(signature)
            .Replace('+', '-')
            .Replace('/', '_')
            .Replace("=", "");

        return $"https://{distributionDomain}{resourcePath}?Expires={epochTime}&Signature={urlSafeSignature}&Key-Pair-Id={keyPairId}";
    }
}

内容的提问来源于stack exchange,提问作者Amy C

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 11:21:04