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); }