2012-07-16 71 views
5

我正在做的HttpWebRequest到S3,和我想的日期頭設置是這樣的:C#HttpWebRequest的日期標題格式

「星期一,2012年7月16日1時16分十八秒 - 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禁止 - 請求時間和服務器時間的差異太大。

任何建議讓這個日期整理出來將不勝感激。謝謝!

回答

13

有一些事情要澄清修複用手請求的情況下:

  • 你的日期模式不正確。

  • 的HttpWebRequest的request.Date頭只能得到改性在.NET框架4並根據該文檔中,命名空間System.Net將總是寫此標頭如使用GMT(UTC)格式標準形式。所以,無論你如何設置格式化日期,都無濟於事!

  • 在其他.NET框架版本中,您將無法修改HttpWebRequest request.Date標頭,因爲它將使用實際日期,格式爲正確的GMT(UTC)格式,除非您使用某種破解來設置自己的日期和格式(見下文)。


解決您的問題(測試工作):

你進口:

using System.Net; 
using System.Reflection; 

獲取格式今天的日期:星期一,2012年7月16日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的日期頭球攻門!

希望這有助於:-)

+1

你是男人。 – Mitciv 2012-07-16 18:16:33

+1

偉大的解決方案和示例。我必須爲我的日期使用UNIX時間戳(十進制),這是一個完美的解決方案。乾杯! – wloescher 2013-05-05 20:57:34

+1

我希望我能多勞多得!很好的回答:) – Winnie 2017-09-26 03:39:02

1

HttpWebRequest將自行正確格式化日期。你的問題是你必須提交一個有效的當前日期。你必須檢查計算機的時鐘是準確的,然後你要發送的正確日期有關的時區和UTC和GMT問題...

嘗試兩種:

request.Date = DateTime.Now; 
request.Date = DateTime.UtcNow; 

的那一個需要工作(如果HttpWebRequest被正確實現,兩者都應該工作)。

在不工作,請使用fiddler看看發生了什麼事,直到你得到它的工作

0

假設你要設置的日期標頭Authorization頭工作。

亞馬遜提供了另一個自定義標題,它將用來代替日期(如果提供)。如果您無法設置Date標頭,則可以使用自定義標頭x-amz-date代替。

這裏的鏈接到亞馬遜的文檔here

+0

請在這篇文章中發佈更多信息,而不是簡單地離開一個鏈接。這對未來的訪問者更有用,在搜索中顯示得更好,並且如果鏈接不好就會持續。 – 2013-05-17 18:30:02

0

您應該使用 「X-AMZ-日期」 標題。

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<string, string> headersDictionary = new SortedDictionary<string, string>(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); 
     }