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

使用S3预签名POST上传文件时遭遇AccessDenied错误排查

预签名POST上传S3时AccessDenied问题排查与解决

问题概述

通过Lambda生成S3预签名POST信息,在Postman中构造表单上传文件时持续收到403 AccessDenied错误。已配置Lambda权限(含PutObject、多部分上传相关权限)、关闭桶的公共访问拦截、设置宽松CORS策略,但问题仍存在。

可能的原因与解决方法

1. Key参数未替换为实际文件名

生成预签名POST时使用了Key="${filename}"作为占位符,但上传时如果未将key字段的值替换为真实的文件名,会导致请求与Policy中的条件不匹配,触发AccessDenied。

解决:

  • 在Postman中,将key字段的值从${filename}改为实际要上传的文件名(如test.jpg);
  • 若需支持动态文件名,修改生成代码的条件为starts-with规则,允许任意Key前缀:
    conditions = [
        {"acl": "private"},
        ["starts-with", "$key", ""]
    ]
    

2. Postman表单字段遗漏或错误

预签名POST返回的fields中的所有参数(acl、key、AWSAccessKeyId、x-amz-security-token、policy、signature)必须全部作为表单字段添加,且字段名需完全匹配(区分大小写)。

检查点:

  • 确认所有字段都已添加,无遗漏;
  • 确保x-amz-security-token字段完整复制(STS临时凭证较长,容易截断);
  • 字段值无多余空格或格式错误。

3. Policy文档条件不匹配

预签名POST的policy是Base64编码的JSON文档,包含上传的权限和条件。若实际请求参数与Policy中的条件不符,会直接被拒绝。

调试方法:

  • 将返回的policy值进行Base64解码,查看其中的expiration(是否已过期)和conditions(是否与上传参数匹配);
  • 示例解码后的Policy:
    {
      "expiration": "2024-05-20T15:30:00Z",
      "conditions": [
        {"acl": "private"},
        {"bucket": "my-bucket"},
        ["eq", "$key", "${filename}"]
      ]
    }
    
    若key条件是固定的${filename},但上传时未替换,就会触发不匹配。

4. 临时凭证有效性问题

Lambda使用的是STS临时凭证(包含x-amz-security-token),若凭证已过期,或传递时出现截断/错误,会导致权限验证失败。

检查点:

  • 确认生成预签名POST后尽快测试,避免凭证过期(默认Lambda临时凭证有效期为1小时);
  • 完整复制x-amz-security-token的值,无遗漏字符。

关键调试步骤

  1. 开启S3访问日志
    为S3桶开启访问日志,日志中会包含具体的错误代码(如InvalidPolicyDocument、SignatureDoesNotMatch)和详细原因,是定位问题最有效的方式。

  2. 简化测试场景
    暂时去掉acl字段和对应的条件,生成最简版本的预签名POST,测试是否能成功上传。若成功,再逐步添加条件排查冲突点:

    response = s3_client.generate_presigned_post(
        Bucket='my-bucket',
        Key="test.jpg"  # 使用固定文件名
    )
    
  3. 验证请求签名
    确保Postman中的所有表单参数都参与了签名计算,不要添加额外的自定义头或参数,避免破坏签名验证。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 15:06:38