生成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
相关产品推荐
相关产品推荐

