S3预签名URL上传文件带x-amz-checksum-sha256报403求助
S3预签名URL PUT请求添加SHA256校验和触发403的解决方法
问题场景
我们在实现S3对象完整性校验时,分段上传通过CompleteMultipartUploadAsync传入ChecksumSHA256参数功能正常:
var completeRequest = new CompleteMultipartUploadRequest { BucketName = bucketName, Key = key, UploadId = uploadId, ChecksumSHA256 = sha256ofFile }; completeRequest.AddPartETags(parts.Select(p => new PartETag(p.PartNumber, p.ETag)).ToArray()); await amazonS3Client.CompleteMultipartUploadAsync(completeRequest);
但小文件使用预签名URL上传时,添加x-amz-checksum-sha256请求头会返回403 Forbidden:
public async Task SimplePutAsync(string presignedURL, ByteArrayContent content, string sha256ofFile) { var httpClient = new HttpClient(); content.Headers.Add("x-amz-checksum-sha256", sha256ofFile); var response = await httpClient.PutAsync(presignedURL, content); response.EnsureSuccessStatusCode(); }
同时在.NET SDK中遇到以下问题:
- 找不到对应AWS CLI中
generate_presigned_post的等效方法 GetPreSignedUrlRequest的Metadata属性为只读,无法在生成预签名URL时配置GeneratePreSignedURL的additionalProperties参数缺乏官方文档说明
核心原因
预签名URL的签名范围包含请求头,若生成URL时未将x-amz-checksum-sha256纳入签名范围,后续请求携带该头会导致签名不匹配,触发403错误。
解决方案
1. 生成预签名URL时包含校验和请求头
使用GetPreSignedUrlRequest的AddHeader方法,将x-amz-checksum-sha256纳入签名范围:
var preSignRequest = new GetPreSignedUrlRequest { BucketName = bucketName, Key = key, Verb = HttpVerb.PUT, Expires = DateTime.UtcNow.AddHours(1) }; // 添加需要签名的校验和头 preSignRequest.AddHeader("x-amz-checksum-sha256", sha256ofFile); string presignedUrl = amazonS3Client.GetPreSignedURL(preSignRequest);
生成后的URL允许请求携带该头,此时执行SimplePutAsync即可正常通过校验。
2. 使用Post预签名上传(对应generate_presigned_post)
.NET SDK提供GeneratePresignedPost方法,支持表单上传并指定校验和条件:
var postPolicy = new PostPolicy { Bucket = bucketName, Key = key, Expires = DateTime.UtcNow.AddHours(1) }; // 添加校验和匹配条件 postPolicy.Conditions.Add(new Condition("x-amz-checksum-sha256", sha256ofFile)); var presignedPost = amazonS3Client.GeneratePresignedPost(postPolicy); // 后续可通过presignedPost.Url和presignedPost.FormFields构造表单上传请求
3. 利用additionalProperties参数传递校验和
GeneratePreSignedURL的additionalProperties参数可传入需要签名的自定义头或参数:
var additionalProps = new Dictionary<string, string> { {"x-amz-checksum-sha256", sha256ofFile} }; string presignedUrl = amazonS3Client.GeneratePreSignedURL( bucketName: bucketName, key: key, expiresIn: TimeSpan.FromHours(1), verb: HttpVerb.PUT, additionalProperties: additionalProps );
该参数会将指定键值对纳入签名范围,确保请求携带对应值时签名验证通过。
内容的提问来源于stack exchange,提问作者Sabarish Sathasivan
相关产品推荐
相关产品推荐

