0

azure table query rest api 因 AuthenticationFailed 错误而失败。

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
  <error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
      <code>AuthenticationFailed</code>
      <message xml:lang="en-US">Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.</message>
   </error>

形成并进行其余调用的 winjs 应用程序代码片段是:

var date = new Date().toGMTString().replace('UTC', 'GMT');
var xhrOption = {
    type: 'GET',
    url: url,
    headers: {
        'content-type': 'application/atom+xml;charset="utf-8"',
        'content-length': 0,
        dataserviceversion: '1.0;NetFx',
        maxdataserviceversion: '2.0;NetFx',
        'x-ms-version': '2011-08-18',
        'x-ms-date': date,
        accept: 'application/atom+xml,application/xml',
        'Accept-Charset': 'UTF-8',
    },
};

xhrOption.headers.Authorization = AuthorizationHeader().computeForTableService(options, xhrOption);

计算授权标头的代码有点长。下面列出:

_getSignatureStringForTableService: function getSignatureStringForTableService()
{
    var headers = this.xhrOptions.headers;
    var httpVerb = this.xhrOptions.type.toUpperCase();
    var sigItems = [];
    sigItems.push(httpVerb);
    var contentMD5 = this._getHeaderOrDefault(headers, 'Content-MD5');
    sigItems.push(contentMD5);
    var contentType = this._getHeaderOrDefault(headers, 'content-type');
    sigItems.push(contentType);
    var date = this._getHeaderOrDefault(headers, 'x-ms-date');
    if (!date)
        date = this._getHeaderOrDefault(headers, 'Date');
    sigItems.push(date);
    var canonicalizedResource = this._getCanonicalizedResource();
    sigItems.push(canonicalizedResource);
    var result = sigItems.join('\n');
    return result;
},
_getCanonicalizedResource: function getCanonicalizedResource()
{
    var items = [];
    var path;
    if (config.storageAccount.isDevStorage)
        path = "/" + config.storageAccount.name + '/' + config.storageAccount.name;
    else
        path = "/" + config.storageAccount.name;

    path += "/" + this.options.resourcePath;
    items.push(path);
    var result = items.join('\n');
    return result;
},
computeForTableService: function computeForTableService(options, xhrOptions)
{
    this.options = options;
    this.xhrOptions = xhrOptions;
    var sig = this._computeSignatureForTableService();
    var result = 'SharedKey ' + config.storageAccount.name + ':' + sig;
    return result;
},
_computeSignatureForTableService: function computeSignatureForTableService()
{
    var sigString = this._getSignatureStringForTableService();

    // TODO: use crypto from windows api. currently uses, google cryptoJS lib
    var key = CryptoJS.enc.Base64.parse(config.storageAccount.primaryKey);
    var hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key);
    hmac.update(sigString);
    var hash = hmac.finalize();
    var result = hash.toString(CryptoJS.enc.Base64);
    return result;
},

有趣的是,我在 2 天前让整个代码运行良好。我已更新服务代码以使用更新的 azure nodejs sdk。我想知道更新是否导致发布者/消费者代码不兼容?

其他意见

  1. 使用 azure nodejs 模块的服务代码能够无误地查询表存储。
  2. 我通过 azure nodejs 模块进行了调试,查看了 stringToSign 并与 winjs 代码生成的内容相匹配。两者都是一样的。
  3. 服务已升级为使用 0.10.x 节点和各自最新的 azure nodejs sdk。
  4. 示例:stringToSign

    GET\n\napplication/atom+xml;charset="utf-8"\nWed, 5 Jun 2013 14:43:30 GMT\n/devstoreaccount1/devstoreaccount1/mytable()

感谢您浏览详细信息。

4

1 回答 1

1

最后 - 错误的根本原因已经解决。问题是x-ms-date标题的价值。

期望值 -Thu, 06 Jun 2013 08:09:50 GMT 在上面的代码中计算的值 -Thu, 6 Jun 2013 08:20:34 GMT

日期之前的0缺失是此错误的根本原因。因此,用于计算授权标头的 stringToSign 是不正确的。因此,授权标头不正确导致 AuthenticationFailed 错误。这也解释了该代码几天前工作的原因(五月底 - 日期有两位数)。

如果 MS 的某个人正在阅读本文,那么拥有适量的详细信息以及错误代码将非常有用。AuthenticationFailed单独的错误代码并不能为开发人员提供任何线索。

我之前使用过 azure storage blob rest api。它为相同的 AuthenticationFailed 错误代码返回更好的错误。它expected stringToSignfound stringToSignAuthenticationFailed 错误代码一起发送。它更有帮助,并且错误在几分钟内得到解决。

使用Microsoft 的网络监视器。编写了 c# 代码片段以使用 azure .net sdk 进行 azure 表查询,并逐个字符比较每个标题以解决问题。

于 2013-06-06T11:26:37.847 回答