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。我想知道更新是否在发布者/消费者代码中引起了一些不确定?
其他观察
示例:stringToSign
GET\n\napplication/atom+xml;charset="utf-8"\nWed, 5 Jun 2013 14:43:30 GMT\n/devstoreaccount1/devstoreaccount1/mytable()
感谢您详细了解。
答案 0 :(得分:1)
最后 - 错误的根本原因已经消失。问题是x-ms-date
标题的价值。
预期价值 - Thu, 06 Jun 2013 08:09:50 GMT
在上面的代码中计算的值 - Thu, 6 Jun 2013 08:20:34 GMT
日期之前丢失的0
是此错误的根本原因。因此,用于计算授权标头的stringToSign不正确。因此,授权标头不正确导致AuthenticationFailed错误。这也解释了为什么这段代码工作几天的原因(5月底 - 日期有两位数)。
如果来自MS的某人正在阅读此内容,那么获得正确数量的详细信息以及错误代码将非常有用。仅AuthenticationFailed
错误代码并未向开发人员提供任何线索。
我之前使用过azure storage blob rest api。它为相同的AuthenticationFailed错误代码返回更好的错误。它通过expected stringToSign
和found stringToSign
以及AuthenticationFailed错误代码发送。它是非常有用的,几分钟就可以解决bug。
来自Microsoft的Network monitor。编写了c#代码片段,使用azure .net sdk进行azure表查询,并逐个字符地比较每个标题以解决问题。