S3生成的PreSigned PUT URL在PostMan可用但C# HttpClient返回403
问题原因分析
- 最核心的错误是ContentType不匹配导致S3签名校验失败
你生成预签名URL时,GetPreSignedUrlRequest里指定的ContentType是纯application/json,S3生成签名时会把这个值纳入签名计算范围。
但是你发起请求时使用new StringContent(mooStr, Encoding.ASCII, "application/json")构造请求体,.NET会自动给Content-Type请求头追加charset=ASCII后缀,最终实际发送的Content-Type为application/json; charset=ascii,和生成签名时的Content-Type不一致,直接触发S3的签名校验失败,返回403错误。 - 次要排查点:确认你的
HttpClient实例没有全局配置额外的请求头(比如Authorization头、x-amz-*类的自定义头),如果有额外头被自动附加到请求中,也会导致签名校验不通过。
修复方案
- 构造请求体后手动覆盖Content-Type头,去掉charset后缀:
var content = new StringContent(mooStr, Encoding.ASCII, "application/json"); // 新增这行覆盖自动生成的Content-Type content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); var fileStreamResponse = await httpClient.PutAsync(url, content);
- 也可以在生成预签名URL时,将ContentType设置为带对应charset的完整值,和请求时保持一致即可。
内容的提问来源于stack exchange,提问作者Pete Roberts
相关产品推荐
相关产品推荐

