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

生成S3预签名上传URL遇SignatureDoesNotMatch错误求助

问题:S3预签名URL在Lambda生成后触发SignatureDoesNotMatch错误,本地正常

本地IDE生成的S3上传预签名URL可正常完成文件上传,但通过AWS Lambda生成的相同逻辑URL触发以下错误:

"The request signature we calculated does not match the signature you provided. Check your key and signing method."

本地IDE代码

def signed_url(): #My code on IDE - below code is placed under lambda_handler on aws lambda

    region = "us-east-1"
    bucket_name = "########"
    aws_s3_access_key_id = "########"
    aws_s3_secret_access_key = "########"
    expiration = datetime.datetime.now() + datetime.timedelta(minutes=5)
    
    my_config = Config(
    region_name = region,
    signature_version = 'v4'
    )
    
    s3_client = boto3.client(
    's3',
    aws_access_key_id=aws_s3_access_key_id,
    aws_secret_access_key=aws_s3_secret_access_key,
    config=my_config
    )
    
    upload_key = uuid.uuid4().hex

    put_url = s3_client.generate_presigned_url(
                ClientMethod='put_object',
                Params={'Bucket': bucket_name, 'Key': upload_key},
                ExpiresIn=3600,
                HttpMethod='PUT'
            )
    return {
        'statusCode': 200,
        'uuid4': upload_key,
        "upload_url": urllib.parse.unquote(put_url),
        "url_raw": put_url
    }

Lambda环境代码

import boto3
import datetime
import uuid
import urllib.parse
from botocore.config import Config
import config_file

def lambda_handler(event, context):
    
    expiration = datetime.datetime.now() + datetime.timedelta(minutes=5)
    
    my_config = Config(
    region_name = config_file.region,
    signature_version = 'v4'
    )
    
    s3_client = boto3.client(
    config_file.service_s3,
    aws_access_key_id = config_file.aws_s3_access_key_id,
    aws_secret_access_key = config_file.aws_s3_secret_access_key,
    config = my_config
    )
    
    upload_key = uuid.uuid4().hex

    put_url = s3_client.generate_presigned_url(
                ClientMethod='put_object',
                Params={'Bucket': config_file.bucket_name, 'Key': upload_key},
                ExpiresIn=3600,
                HttpMethod='PUT'
            )
            
    return {
        'statusCode': 200,
        'uuid4': upload_key,
        "upload_url": urllib.parse.unquote(put_url),
        "url_raw": put_url
    }

解决方法

  • 检查config_file配置一致性

    • 确认config_file.region的值与本地代码的us-east-1完全一致,S3 V4签名对region严格匹配,region错误会直接导致签名不匹配。
    • 验证config_file.service_s3的值为s3,boto3.client的第一个参数必须是正确的服务名称,错误值会导致客户端初始化异常,生成无效签名。
    • 核对config_file.aws_s3_access_key_id和config_file.aws_s3_secret_access_key,确保无多余空格、换行符,且与本地使用的密钥完全相同。
  • 改用Lambda执行角色生成预签名URL
    Lambda不需要硬编码Access Key,给Lambda执行角色附加允许s3:PutObject的IAM权限后,直接初始化S3客户端即可自动获取临时凭证:

    s3_client = boto3.client(
        's3',
        config=my_config
    )
    

    硬编码密钥不仅不安全,还容易因配置注入错误导致签名问题。

  • 验证URL使用方式
    确认前端或调用方使用的是url_raw字段的原始预签名URL,而非upload_url的解码版本。预签名URL中的签名部分经过URL编码,解码后会破坏签名结构,导致验证失败。

  • 排查时间同步问题
    在Lambda中打印当前UTC时间(datetime.datetime.utcnow()),确认与标准UTC时间无明显偏移。签名依赖时间戳,时间偏差过大(超过5分钟)会触发S3的签名验证失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 08:47:50