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

S3预签名URL返回403错误排查:Bucket与Lambda权限均正常

问题描述

项目架构:Client -> API Gateway -> Lambda -> 预签名URL;用户获取预签名URL后向S3发起请求。已成功生成并返回预签名URL,但通过Postman或fetch调用时始终返回403错误。

客户端上传代码

async function uploadPic()
{
    // 获取输入文件...
    var fileName = file.name;

    // uploadEventPhoto从URL获取Cognito idToken并请求预签名URL,Cognito功能正常,已在其他API资源验证
    let url = await uploadEventPhoto(idToken)

    // 尝试过用formData和直接传文件,都不影响403错误
    let formData = new FormData()
    formData.append("file", file)
   
    const requestOptions = {
        method: 'PUT',
        headers: {
            'Content-Type': "multipart/form-data"
        },
        body: formData
    };
   
    let putURLResponse= await fetch(url, requestOptions)
}

Lambda生成预签名URL代码

def lambda_handler(event, context):
    # 生成随机字符串的函数已省略,功能正常
    rand_id = generate_random_string(8)

    client = boto3.client('s3',aws_access_key_id='REDACTED',aws_secret_access_key='REDACTED')
    resp = client.generate_presigned_url("put_object",
        Params={
            "Bucket":"REDACTED",
            "Key":"REDACTED/REDACTED"
        },
        ExpiresIn=300
        )

    return {
        'statusCode': 200,
        'headers': {
            'Content-Type': 'image/png',
            'Access-Control-Allow-Origin': '*',
            'Access-Control-Allow-Methods': 'POST, PUT, GET, OPTIONS',
            'Access-Control-Allow-Headers': 'Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With'
        },
        'body': json.dumps(resp)
    }

客户端获取预签名URL函数

async function uploadEventPhoto(idToken)
{
    // 函数名有误,原本是想传数据给Lambda写入S3,现在仅用Cognito认证调用Lambda获取预签名URL
    const url = 'https://REDACTED.execute-api.us-west-1.amazonaws.com/dev/Photos';
    const requestOptions = {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${idToken}`
        },
    };

    let resp = await fetch(url, requestOptions)
    let data = await resp.json()
    return data
}

S3 Bucket政策

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::REDACTED/*"
        },
        {
            "Sid": "S3PolicyStmt-DO-NOT-MODIFY-1719269888596",
            "Effect": "Allow",
            "Principal": {
                "Service": "logging.s3.amazonaws.com"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::REDACTED/*",
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": "REDACTED"
                }
            }
        },
        {
            "Sid": "Statement1",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:PutObjectAcl",
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::REDACTED/*",
                "arn:aws:s3:::REDACTED"
            ]
        }
    ]
}

角色/用户配置

  • 已确认Lambda角色拥有S3权限,最初仅配置putObject,现在改为全权限覆盖所有场景
  • 尝试创建新角色并配置正确权限,问题依旧
  • 创建新用户并赋予S3权限,在客户端使用其访问密钥,期望用户权限传递到URL,无效
  • 尝试不在客户端构造器中使用访问密钥,测试传递Lambda权限,两种方式均无效

S3 Bucket配置

  • 最初仅配置公共读取权限,现在改为公共读写权限,仍无法解决403错误
  • CORS允许所有来源和方法
  • 确保角色拥有对arn:aws:s3:::REDACTED和arn:aws:s3:::REDACTED/*的访问权限
  • 尝试为角色赋予KMS权限,参考相关帖子,无效

其他排查步骤

  • 尝试使用presigned_put_url()无效,切换为presigned_url()仍无法解决
  • 使用权限模拟器测试用户和角色向S3 Bucket上传的权限,结果显示均正常
  • 请求链接包含角色的AWSAccessKeyID,看似用户权限已传递,但访问顾问显示密钥未被访问
  • 已尝试更多无法记起的排查步骤,问题仍未解决

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 00:32:10