我一直在关注blob service和authentication documentation,以便从我的移动服务中设置我的azure blob存储帐户的CORS属性。
我无法弄清楚我做错了什么。
服务器响应是:
在HTTP请求'JI ... Tk ='中找到的MAC签名与任何计算签名不同。服务器使用以下字符串进行签名:'PUT
x-ms-date:Wed,2014年2月19日07:24:06 GMT x-ms-version:2013-08-15 / apporotest /?排版=属性
当我在字符串上记录字符串以进行签名(不传递contentMD5和内容类型)时,结果是相同的字符串。所以我猜我构建共享密钥的功能是错误的。
这应该构建:Base64(HMAC-SHA256(UTF8(StringToSign))):
function buildSharedKeyLite( verb, contentMD5, contentType, canonicalizedHeaders, canonicalizedResource ) {
var stringToSign = verb + "\n" +
contentMD5 + "\n" +
contentType + "\n" +
"" + "\n" + // date is to be empty because we use x-ms-date
canonicalizedHeaders +
canonicalizedResource;
return crypto.createHmac('sha256', self.accountKey).update(encodeURIComponent(stringToSign)).digest('base64');
}
令我困惑的是,前面提到的Shared Key Lite文档需要内容的MD5以及要设置的内容类型。但是,带有要签名的字符串的服务器响应似乎并不期望这些。
如果共享密钥精简版的创建是正确的,那么我假设我没有正确处理MD-5内容的创建或规范化标题:
function setCors( cors ) {
var url = MY_ACCOUNT_UTL + '/?restype=service&comp=properties';
var canonicalizedResource = '/' + MY_ACCOUNT_NAME + '/?comp=properties';
var corsMD5 = crypto.createHash('md5' ).update(MY_CORS_XML).digest('base64');
var date = (new Date()).toUTCString();
var headers = {
'x-ms-version': '2013-08-15',
'x-ms-date': date,
'Host': MY_ACCOUNT_HOST
};
var canonicalizedHeaders = buildCanonicalizedHeaders( headers );
// THIS
var key = buildSharedKeyLite( 'PUT', corsMD5, 'text/plain; charset=UTF-8', canonicalizedHeaders, canonicalizedResource );
// AND THIS, BOTH YIELD THE SAME SERVER RESPONSE
var key = buildSharedKeyLite( 'PUT', "", "", canonicalizedHeaders, canonicalizedResource );
headers['Authorization'] = 'SharedKeyLite ' + MY_ACCOUNT_NAME + ':' + key;
var options = {
url: url,
headers: headers
};
function onPropertiesSet(error, response, body) {
if (!error && response.statusCode == 202) {
console.log("CORS: OK");
}
else {
console.log("CORS: "+ response.statusCode);
console.log(body);
}
}
request.put(options, onPropertiesSet); // require('request')
}
function buildCanonicalizedHeaders( headers ) {
var xmsHeaders = [];
var canHeaders = "";
for ( var name in headers ) {
if ( name.indexOf('x-ms-') == 0 ) )
xmsHeaders.push( name );
}
}
xmsHeaders.sort();
for ( var i = 0; i < xmsHeaders.length; i++ ) {
name = xmsHeaders[i];
canHeaders = canHeaders + name.toLowerCase().trim() + ':' + headers[name] + '\n';
}
return canHeaders;
}
我非常感谢任何指示。
答案 0 :(得分:1)
我不是百分百肯定,但我相信encodeURIComponent
正在给你带来麻烦。例如,请查看以下代码:
var a = "PUT\n\n\nFeb 2014 09:08:18 GMT\nx-ms-version:2013-08-15\n/cynapta/?comp=properties";
var b = encodeURIComponent(a);
console.log(a);
console.log("\n");
console.log(b);
这就是我的控制台上显示a
和b
的方式:
您可以尝试删除encodeURIComponent
并直接通过stringToSign
进行签名计算吗?
<强>更新强>
查看用于签署请求的源代码here
并假设您将存储帐户密钥作为字符串传递,您可以在buildSharedKeyLite
函数中尝试以下操作:
return crypto.createHmac('sha256', new Buffer(self.accountKey, 'base64')).update(stringToSign).digest('base64');