我正在创建能够将一些blob上传到Azure存储的Windows Phone 8.1 Store App。我不能使用WindowsAzure.Storage lib(非常奇怪),所以我试图使用REST。我无法弄清楚,有什么不对。
try
{
string time = DateTime.Now.ToString("R", System.Globalization.CultureInfo.InvariantCulture);
string tosign = "GET\n" +
"\n" + //Content-Encoding
"\n" + //Content-Language
"0\n" + //Content-Length
"\n" + //Content-MD5
"\n" + //Content-Type
"\n" + //Date
"\n" + //If-modified-since
"\n" + //If-match
"\n" + //If-none-match
"\n" + //If-unmodified-since
"\n" + //Range
"x-ms-date:" + time + "\nx-ms-version:2015-02-21\n" + //CanonicalizedHeaders
"/storage_name/\ncomp:list"; //CanonicalizedResource
string hashKey = "DHpNuYG5MXhamfbKmFPClUlNi38QiM2uqIqz07pgvpv2gmXJRwxaMlcV05pFCYsrelGYKPed9QphyJ/YnUrh5w=="; //Primary access key
MacAlgorithmProvider macAlgorithmProvider = MacAlgorithmProvider.OpenAlgorithm(MacAlgorithmNames.HmacSha256);
var messageBuffer = CryptographicBuffer.ConvertStringToBinary(tosign, BinaryStringEncoding.Utf8);
IBuffer keyBuffer = CryptographicBuffer.ConvertStringToBinary(hashKey, BinaryStringEncoding.Utf8);
CryptographicKey hmacKey = macAlgorithmProvider.CreateKey(keyBuffer);
IBuffer signedMessage = CryptographicEngine.Sign(hmacKey, messageBuffer);
string hashedString = CryptographicBuffer.EncodeToBase64String(signedMessage);
var client = new HttpClient();
Uri uri = new Uri("https://storage_name.blob.core.windows.net/?comp=list");
client.DefaultRequestHeaders.Add("x-ms-date", time);
client.DefaultRequestHeaders.Add("x-ms-version", "2015-02-21");
client.DefaultRequestHeaders.Add("Authorization", "SharedKey storage_name:" + hashedString);
var response = await client.GetAsync(uri);
}
catch(Exception ex)
{
Debug.WriteLine(ex.ToString());
}
错误:服务器无法验证请求。确保正确形成Authorization标头的值,包括签名。
我如何才能使它发挥作用?
答案 0 :(得分:3)
您的加密代码出错了。 : - )
以下是工作代码示例,它们在UTF-8编码的签名字符串上调用HMAC-SHA256算法,并将结果编码为Base64。"在下面的示例中, class View: UIView {
func drawRooftopAtTopPointOf(point: CGPoint){
UIColor.redColor().set()
let context = UIGraphicsGetCurrentContext()
CGContextSetLineWidth(context, 5)
CGContextMoveToPoint(context, 140, 100)
CGContextAddLineToPoint(context, 140, 50)
CGContextStrokePath(context)
参数是"主要访问密钥"来自Azure,hashKey
参数是"签名字符串"来自docs。
在Windows Phone 8.1上,我们使用toSign
命名空间,如下所示:
Windows.Security.Cryptography
我还创建了使用public string GetEncodedSignature(string toSign, string hashKey)
{
// UTF-8-encoded signature string
var utf8 = BinaryStringEncoding.Utf8;
var msgBuffer = CryptographicBuffer.ConvertStringToBinary(toSign, utf8);
// primary access key
// note the use of DecodeFromBase64String
var keyBuffer = CryptographicBuffer.DecodeFromBase64String(hashKey);
// make the HMAC-SHA256 algorithm
var alg = MacAlgorithmNames.HmacSha256;
var objMacProv = MacAlgorithmProvider.OpenAlgorithm(alg);
CryptographicHash hash = objMacProv.CreateHash(keyBuffer);
// call the HMAC-SHA256 algorithm
hash.Append(msgBuffer);
IBuffer hashMsg = hash.GetValueAndReset();
// retrieve the result!
var result = CryptographicBuffer.EncodeToBase64String(hashMsg);
return result;
}
命名空间的an example for .NET。
System.Security.Cryptography
两个代码示例在给定相同输入时产生相同的编码签名。您可以在此Fiddle that generates the HTTP Request更详细地查看其中一个。
答案 1 :(得分:1)
可能你已经解决了这个问题,但如果没有,或者对于其他任何人,我只是遇到了同样的问题,对我而言,修复它的内容是将内容长度改为" \ n& #34; (而不是" 0 \ n")。从2015-02-21及更高版本开始,您无需指定长度。
try
{
string time = DateTime.Now.ToString("R", System.Globalization.CultureInfo.InvariantCulture);
string tosign = "GET\n" +
"\n" + //Content-Encoding
"\n" + //Content-Language
"\n" + //Content-Length
"\n" + //Content-MD5
"\n" + //Content-Type
"\n" + //Date
"\n" + //If-modified-since
"\n" + //If-match
"\n" + //If-none-match
"\n" + //If-unmodified-since
"\n" + //Range
"x-ms-date:" + time + "\nx-ms-version:2015-02-21\n" + //CanonicalizedHeaders
"/storage_name/\ncomp:list"; //CanonicalizedResource
string hashKey = "DHpNuYG5MXhamfbKmFPClUlNi38QiM2uqIqz07pgvpv2gmXJRwxaMlcV05pFCYsrelGYKPed9QphyJ/YnUrh5w=="; //Primary access key
string hashedString = GetEncodedSignature(tosign, hashKey); //Shaun's answer method
var client = new HttpClient();
Uri uri = new Uri("https://storage_name.blob.core.windows.net/?comp=list");
client.DefaultRequestHeaders.Add("x-ms-date", time);
client.DefaultRequestHeaders.Add("x-ms-version", "2015-02-21");
client.DefaultRequestHeaders.Add("Authorization", "SharedKey storage_name:" + hashedString);
var response = await client.GetAsync(uri);
}
catch(Exception ex)
{
Debug.WriteLine(ex.ToString());
}