C#HttpWebRequest日期标题格式
我正在向S3做一个HttpWebRequest,我正在尝试将Date标头设置为这样的:
“星期一,2012年7月16日01:16:18 -0000”
这是我尝试过的:
string pattern = "ddd, dd MMM yyyy HH:mm:ss -0000"; request.Date = DateTime.ParseExact("Mon, 16 Jul 2012 01:16:18 -0000", pattern, null);
但是,当我查看请求的标题时,这是我得到的:
request.Headers.Get("Date"); // "Mon, 16 Jul 2012 07:16:18 GMT"
我相信这可能是请求403的原因。 AWS错误文档提到:
403 Forbidden – 请求时间与服务器时间之间的差异太大。
任何有关将此日期整理出来的建议将不胜感激。 谢谢!
有一些事情需要澄清:
-
您的日期模式不正确。
-
HttpWebRequest
request.Date
标头只能在.NET Framework 4中进行修改,并且根据文档,System.Net
命名空间将始终使用GMT(UTC)格式将此标头写为标准格式 。 所以,无论你怎么做你想要的日期格式,都行不通! -
在其他.NET框架版本中,您将无法修改HttpWebRequest
request.Date
标头,因为它将以正确的GMT(UTC)格式使用实际日期,除非您使用某种黑客来设置自己的日期和格式(请参阅下面)。
解决您的问题(测试和工作):
你的import:
using System.Net; using System.Reflection;
今天的格式为:Mon,16 Jul 2012 01:16:18 -0000
string today = String.Format("{0:ddd,' 'dd' 'MMM' 'yyyy' 'HH':'mm':'ss' 'K}", DateTime.Now);
这是棘手的事情,你可以通过这样做来破解HttpWebRequest日期标题:
(不要做request.Date = something;
再用以下内容替换它)
MethodInfo priMethod = request.Headers.GetType().GetMethod("AddWithoutValidate", BindingFlags.Instance | BindingFlags.NonPublic); priMethod.Invoke(request.Headers, new[] { "Date", today });
从您的请求中获取日期(仅用于测试):
// "myDate" will output the same date as the first moment: // Mon, 16 Jul 2012 01:16:18 -0000 // As you can see, you will never get this again: // Mon, 16 Jul 2012 07:16:18 GMT string myDate = request.Headers.Get("Date");
此时,您已成功将自己的格式和日期值设置为HttpWebRequest日期标题!
希望这可以帮助 :-)
HttpWebRequest将自己正确格式化Date。 您的问题是您必须提交有效的当前日期。 你必须检查计算机的时钟是否准确,然后你发送关于时区和UTC和GMT问题的正确日期……
试试两个:
request.Date = DateTime.Now; request.Date = DateTime.UtcNow;
其中一个需要工作(如果HttpWebRequest正确实现,两者都应该工作)。
如果不起作用,请使用fiddler查看发生了什么,并手动修复请求,直到它开始工作
假设您要将Authorization标头的Date标头设置为可用。
亚马逊提供另一个自定义标头,用于代替日期(如果提供)。 如果您无法设置日期标题,则可以使用自定义标题x-amz-date。
这里是亚马逊文档的链接
您应该使用“X-Amz-Date”标题。
public void GetObject(string AccessKeyID, string SecretKey){ /*objectKey = folder/folder/filename.zzz*/ var url = "http://somehost/bucket/objectkey" HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url); /*Fiddler proxy*/ /*request.Proxy = new WebProxy("http://127.0.0.1:8888");*/ request.Headers.Add("X-Amz-Date",String.Format("{0:ddd,' 'dd' 'MMM' 'yyyy' 'HH':'mm':'ss' 'K}", DateTime.Now)); request.Headers.Add("Authorization", $"AWS {AccessKeyID}:{SignAuthorizationString(request, SecretKey)}"); WebResponse response = request.GetResponse(); } private string SignAuthorizationString(HttpWebRequest request, string SecretKey){ //TODO: DOCS - http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html string canonicalizedResource = request.RequestUri.PathAndQuery; string canonicalizedAmzHeaders = ComposeSignatureAmzHeadersForSigning(request); string stringToSign = request.Method + "\n" + request.Headers.Get("Content-MD5") + "\n" + request.ContentType + "\n" + request.Headers.Get("Date") + "\n" /*Here the date will be blank*/ + canonicalizedAmzHeaders + canonicalizedResource; return GetSignedMessage(SecretKey, stringToSign); } private string ComposeSignatureAmzHeadersForSigning(HttpWebRequest request){ SortedDictionary headersDictionary = new SortedDictionary(StringComparer.OrdinalIgnoreCase); foreach (string _key in request.Headers.Keys) { key = _key.ToLower(); if (key.StartsWith("x-amz")) { if ("x-amz-meta-reviewedby".Equals(key)) { if (headersDictionary.ContainsKey(key)) headersDictionary[key] = headersDictionary[key] + "," + request.Headers[key]; else headersDictionary[key] = request.Headers[key]; } else headersDictionary[key] = request.Headers.Get(key); } } StringBuilder stringBuilder = new StringBuilder(); foreach (var pair in headersDictionary) { stringBuilder.Append(pair.Key) .Append(":") .Append(pair.Value) .Append("\n"); } return stringBuilder.ToString(); } private static string GetSignedMessage(string key, string message){ var crypt = HMACSHA1.Create(); crypt.Key = Encoding.ASCII.GetBytes(key); crypt.ComputeHash(Encoding.UTF8.GetBytes(message)); return Convert.ToBase64String(crypt.Hash); }
- ASP.NET MVC – 将图像上传到Amazon S3
- 处理完响应后,使用Amazon S3响应流
- 如何使用amazon sdk为虚拟域生成预签名的Amazon S3url?
- Amazon S3:如何获取存储桶中的文件夹列表?
- 有没有办法在“公开可读的存储桶”上使用Amazon .NET AWS SDK的AmazonS3客户端而无需指定AWS凭据?
- CompleteMultipartUploadResponse中的EntityTooSmall
- 当我设置包含“+”的响应标头覆盖时,为什么我的S3预签名请求无效?
- 无需访问和密钥即可上传到Amazon S3
- 如何在Amazon S3存储桶中列出_all_对象?