如何使用Node设置Azure Blob存储CORS属性?

时间:2014-02-19 08:18:45

标签: node.js azure

我一直在关注blob serviceauthentication 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;
    }

我非常感谢任何指示。

1 个答案:

答案 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);

这就是我的控制台上显示ab的方式:

enter image description here

您可以尝试删除encodeURIComponent并直接通过stringToSign进行签名计算吗?

<强>更新

查看用于签署请求的源代码here并假设您将存储帐户密钥作为字符串传递,您可以在buildSharedKeyLite函数中尝试以下操作:

return crypto.createHmac('sha256', new Buffer(self.accountKey, 'base64')).update(stringToSign).digest('base64');