8

我正在向 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 - 请求时间与服务器时间相差太大。

任何有关整理此日期的建议将不胜感激。谢谢!

4

4 回答 4

15

有几点需要澄清:

  • 您的日期模式不正确。

  • HttpWebRequestrequest.Date标头只能在 .NET Framework 4 中进行修改,根据文档,System.Net命名空间将始终将此标头写为使用GMT (UTC) 格式的标准格式。所以,无论你做什么来格式化你想要的日期,都行不通!

  • 在其他 .NET 框架版本中,您将无法修改 HttpWebRequestrequest.Date标头,因为它将使用正确的 GMT (UTC) 格式的实际日期,除非您使用某种技巧来设置您自己的日期和格式(见下文)。


您的问题的解决方案(经过测试和工作):

您的进口:

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 日期标头!

希望这可以帮助 :-)

于 2012-07-16T04:22:35.323 回答
1

HttpWebRequest 将自行正确格式化 Date。您的问题是您必须提交一个有效的当前日期。您必须检查计算机的时钟是否准确,然后您要发送有关时区以及 UTC 和 GMT 问题的正确日期...

尝试两者:

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

其中之一需要工作(如果正确实施 HttpWebRequest ,两者都应该工作)。

如果这不起作用,请使用fiddler查看发生了什么,并手动修复请求,直到它正常工作

于 2012-07-16T02:01:29.173 回答
0

假设您要设置 Date 标头以使 Authorization 标头起作用。

Amazon 提供了另一个自定义标头,它将代替 Date(如果提供)。如果您无法设置 Date 标头,则可以使用自定义标头 x-amz-date。

这是亚马逊文档的链接

于 2013-05-17T18:13:36.827 回答
-1

您应该使用“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<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);
        }
于 2016-09-14T09:15:00.300 回答