2012-07-16 12 views
5

Robię HttpWebRequest do S3, a ja staram się ustawić datę nagłówek do czegoś takiego:C# HttpWebRequest Data Header Formatowanie

„Mon, 16 lipca 2012 01:16:18 - 0000"

Oto co próbowałem:

string pattern = "ddd, dd MMM yyyy HH:mm:ss -0000"; 
request.Date = DateTime.ParseExact("Mon, 16 Jul 2012 01:16:18 -0000", pattern, null); 

Ale kiedy patrzę na nagłówkach żądania, oto co mam:

request.Headers.Get("Date"); 
// "Mon, 16 Jul 2012 07:16:18 GMT" 

Wierzę, że może to być przyczyną 403 na żądanie. Docs błędach AWS wymienić:

403. - Różnica pomiędzy czasem żądanie i czasu serwera jest zbyt duża.

Wszelkie sugestie dotyczące uprzątnięcia tej daty będą bardzo mile widziane. Dzięki!

Odpowiedz

13

Jest kilka rzeczy do wyjaśnienia:

  • Twój wzór daty jest nieprawidłowy.

  • Nagłówek HttpWebRequest request.Date można uzyskać modyfikowane tylko w .NET Framework 4 oraz zgodnie z dokumentacją, przestrzeń nazw System.Net zawsze napisać ten nagłówek jako standardowy formularz w formacieGMT (UTC). Więc, cokolwiek możesz zrobić, aby sformatować swoją datę, jak chcesz, nie zadziała!

  • W innych wersjach .NET Framework nie będzie w stanie zmodyfikować HttpWebRequest request.Date nagłówek bo będzie korzystał z rzeczywistą datę w prawidłowym formacie GMT (UTC), chyba że używasz rodzaju hack, aby ustawić datę i swój własny format (patrz poniżej).


rozwiązanie problemu (przetestowane i działa):

Twoje import:

using System.Net; 
using System.Reflection; 

Get dzisiejszą datę w formacie: Mon, 16 Jul 2012 01:16:18 -0000

string today = String.Format("{0:ddd,' 'dd' 'MMM' 'yyyy' 'HH':'mm':'ss' 'K}", DateTime.Now); 

Nadchodzi trudne rzeczy, można siekać datę HttpWebRequest nagłówek w ten sposób:

(Nie rób request.Date = something; już, wymień go poniżej)

MethodInfo priMethod = request.Headers.GetType().GetMethod("AddWithoutValidate", BindingFlags.Instance | BindingFlags.NonPublic); 
priMethod.Invoke(request.Headers, new[] { "Date", today }); 

Uzyskaj datę na żądanie (wystarczy przetestować):

// "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"); 

W tym momencie z powodzeniem ustawiłeś własny format i datę na nagłówek daty HttpWebRequest!

Nadzieja to pomaga :-)

+1

Jesteś mężczyzną. – Mitciv

+1

Doskonałe rozwiązanie i przykład. Muszę użyć znacznika czasu UNIX (dziesiętnego) dla mojej daty, a to było idealne rozwiązanie. Twoje zdrowie! – wloescher

+1

Żałuję, że nie mogłem tego zrobić więcej niż raz! wspaniała odpowiedź :) – Winnie

1

HttpWebRequest odpowiednio sformatuje datę. Twój problem polega na tym, że musisz przesłać prawidłową datę bieżącą. Trzeba sprawdzić, czy zegar komputera jest dokładne, a następnie, że wysyłasz odpowiednią datę dotyczące stref czasowych i zagadnień UTC i GMT ...

spróbować zarówno:

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

że jeden z musi działać (i oba powinny działać, jeśli HttpWebRequest jest poprawnie zaimplementowany).

W przypadku, gdy nie działa, należy skorzystać fiddler aby zobaczyć, co się dzieje, i naprawić wniosek strony, dopóki nie dostać pracy

0

Zakładając chcesz ustawić nagłówek DATY nagłówek autoryzacji do pracy.

Amazon dostarcza inny niestandardowy nagłówek, który będzie używany zamiast daty (jeśli została podana). Jeśli nie możesz ustawić nagłówka Date, możesz zamiast tego użyć niestandardowego nagłówka, x-amz-date.

Oto link do Dokumentów Amazona here

+0

Proszę wstawić więcej informacji w tym poście, zamiast po prostu pozostawić link. Jest bardziej przydatny dla przyszłych użytkowników, lepiej wyświetla się w wyszukiwaniach i będzie się utrzymywał, jeśli link się pogorszy. –

0

należy użyć "X-Amz-Date" nagłówek.

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