S3预签名POST请求中Content-Disposition策略条件失败致AccessDenied错误
S3预签名Post请求Content-Disposition条件匹配失败问题解决
问题场景
使用以下Python代码生成S3预签名Post请求参数:
return s3_resource.meta.client.generate_presigned_post( Bucket=S3Config.BUCKET_NAME, Key=object_key, Fields={ "Content-Disposition": f"filename={filename}", "Content-Type": mime_type }, Conditions=[ {"Content-Disposition": f'filename="{filename}"'}, {"Content-Type": mime_type} ], ExpiresIn=120 )
通过Postman提交表单请求时,收到错误:
return (<Code>AccessDenied</Code> )Invalid according to Policy: Policy Condition failed: ["eq", "$Content-Disposition", "filename="test.png""]
问题原因
代码中Fields里的Content-Disposition格式与Conditions中的不一致:
- Fields里的格式是
filename={filename}(无引号) - Conditions里的格式是
filename="{filename}"(带双引号)
S3会严格校验请求中的Content-Disposition值与Policy里的条件完全匹配,包括引号这类字符,因此导致校验失败。
解决方案
统一Fields和Conditions中Content-Disposition的格式,二选一即可:
方案1:统一为带引号的格式
修改Fields中的Content-Disposition,添加双引号:
return s3_resource.meta.client.generate_presigned_post( Bucket=S3Config.BUCKET_NAME, Key=object_key, Fields={ "Content-Disposition": f'filename="{filename}"', # 统一为带引号格式 "Content-Type": mime_type }, Conditions=[ {"Content-Disposition": f'filename="{filename}"'}, {"Content-Type": mime_type} ], ExpiresIn=120 )
同时确保Postman表单中提交的Content-Disposition值为filename="test.png"(与生成参数完全一致)。
方案2:统一为不带引号的格式
修改Conditions中的Content-Disposition,去掉双引号:
return s3_resource.meta.client.generate_presigned_post( Bucket=S3Config.BUCKET_NAME, Key=object_key, Fields={ "Content-Disposition": f"filename={filename}", "Content-Type": mime_type }, Conditions=[ {"Content-Disposition": f"filename={filename}"}, # 统一为不带引号格式 {"Content-Type": mime_type} ], ExpiresIn=120 )
此时Postman表单中提交的Content-Disposition值应为filename=test.png。
注意事项
- S3的Policy条件匹配是严格字符串匹配,大小写、特殊字符(如引号)都必须完全一致;
- 提交表单时,确保所有参数(包括Content-Disposition、Content-Type)的值与预签名生成的Fields和Conditions完全对应。
内容的提问来源于stack exchange,提问作者Raza Ullah
相关产品推荐
相关产品推荐

