我正在向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 - 请求时间与之间的差异 服务器的时间太长了。
任何有关将此日期整理出来的建议都将非常感谢。谢谢!
答案 0 :(得分:13)
有一些事情需要澄清:
您的日期模式不正确。
HttpWebRequest request.Date
标头只能在.NET Framework 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 :(得分:1)
HttpWebRequest将自行正确格式化Date。您的问题是您必须提交有效的当前日期。你必须检查计算机的时钟是否准确,然后你要发送关于时区和UTC和GMT问题的正确日期......
尝试两者:
request.Date = DateTime.Now;
request.Date = DateTime.UtcNow;
其中一个需要工作(如果HttpWebRequest正确实现,两者都应该有效)。
如果不起作用,请使用fiddler查看正在发生的事情,并手动修复请求,直到您的工作正常进行
答案 2 :(得分:0)
假设您要将Authorization标头的Date标头设置为可用。
Amazon提供另一个自定义标头,用于代替Date(如果提供)。如果您无法设置日期标题,则可以使用自定义标题x-amz-date。
以下是亚马逊文档here
的链接答案 3 :(得分:0)
你应该使用" 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);
}