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

生成S3预签名Post URL遇‘未提供AWSAccessKey’错误求助

解决S3预签名Post请求的AccessDenied(No AWSAccessKey was presented)问题

问题场景

使用boto3生成S3预签名Post URL后,返回的fields中未包含AWSAccessKeyId字段,发起POST请求时收到No AWSAccessKey was presented的权限错误。

生成预签名Post的Python代码

def generate_pre_signed_upload_url(content_type: str, expiration: int, fields, bucket_name: str, object_name: str):
    try:
        config = Config(signature_version='s3v4')
        s3 = boto3.client("s3", region_name='us-west-2', config=config)
        return s3.generate_presigned_post(
            Bucket=bucket_name,
            Key=object_name,
            Fields=fields,
            ExpiresIn=expiration,
            Conditions=[{"Content-Type": content_type}],
        )
    except Exception as e:
        raise e

代码返回结果

{
    "url": "https://sandbox-taxservice-s3bucket-s3bucket6575f0a6-19dl1xpyc3fzo.s3.amazonaws.com/",
    "fields": {
        "key": "xxxxxxxxxxxxx",
        "x-amz-algorithm": "AWS4-HMAC-SHA256",
        "x-amz-credential": "xxxxxxxxx",
        "x-amz-date": "xxxxxx",
        "x-amz-security-token": "xxxxxx",
        "policy": "xxxxxxxx",
        "x-amz-signature": "xxxxxxx"
    }
}

错误响应

<?xml version="1.0" encoding="UTF-8"?>
<Error>
    <Code>AccessDenied</Code>
    <Message>No AWSAccessKey was presented.</Message>
    <RequestId>354BCDQHZ4NB8Y4D</RequestId>
    <HostId>aBM0WkvvrVg9H+Q2H826rHA/bPhxvSGGEg5HKbkxEHwbzybN0p0dhbR4F8np/ovKHJlx9Cwgrgc=</HostId>
</Error>

解决方案

1. 规范请求提交方式

S3预签名Post要求所有fields参数作为表单字段提交,需满足:

  • 请求方法必须为POST
  • 表单enctype设置为multipart/form-data
  • 完整传递fields中的所有键值对(V4签名模式下,x-amz-credential已包含访问密钥ID,无需单独的AWSAccessKeyId字段)

2. 校验IAM权限

确保生成预签名URL的IAM身份(用户/角色)拥有:

  • s3:PutObject权限(针对目标Bucket和指定Key)
  • 若使用临时凭证,需确认凭证未过期且权限范围覆盖目标操作

3. 修正Conditions参数冲突

如果调用函数时传入的fields已包含Content-Type字段,需删除Conditions中的对应条目,避免签名验证冲突。示例调整:

return s3.generate_presigned_post(
    Bucket=bucket_name,
    Key=object_name,
    Fields=fields,
    ExpiresIn=expiration,
    # 若fields已含Content-Type,移除此行
    # Conditions=[{"Content-Type": content_type}],
)

4. 临时 workaround:手动添加AWSAccessKeyId

若上述方法无效,可在调用函数时传入的fields中手动添加该字段:

fields = {
    # 原有字段...
    "AWSAccessKeyId": "你的IAM访问密钥ID"
}

注意:此方法仅作为临时修复,V4签名模式下优先通过规范请求方式解决问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 21:10:20