DocumentDB REST API-授权令牌错误 [英] DocumentDB REST API - Authorization Token Error

查看:110
本文介绍了DocumentDB REST API-授权令牌错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题

每当我们请求列表或查询时,我们都会看到从DocumentDB REST API返回的错误,但是当我们通过名称/id获取对象时却没有:

We are seeing this error returned from the DocumentDB REST API whenever we request a list or query, but not when we fetch objects by name/id:

输入的授权令牌无法处理请求.请检查是否根据协议构建了预期的有效负载,并检查所使用的密钥.

The input authorization token can't serve the request. Please check that the expected payload is built as per the protocol, and check the key being used.

背景

一年多来,我们已经成功地将node.js sdk与DocumentDB一起使用,但是,由于我们希望将后端静态API代码从node.js应用服务迁移到Azure Functions,因此我们看到10-30当一段时间未调用Function时,由于DocumentDB sdk加载缓慢,第二个延迟时间开始起作用.我们知道Function实例很热,根据先前与Azure Functions团队的沟通,这不是一个冷实例问题.

We have been successfully using the node.js sdk with DocumentDB for over a year now, but as we want to migrate our back-end restful API code from a node.js App Service to Azure Functions we are seeing 10-30 second lag times come into play as the DocumentDB sdk loads slowly when the Function hasn't been called in a while. We know that the Function instance is hot, and this isn't a cold instance issue based on previous communication with the Azure Functions team.

要解决此问题,我们要测试DocumentDB REST API,该API需要在node.js函数中运行零个外部库,并且应尽快执行.

To work around this we want to test the DocumentDB REST API which requires zero external libraries to run in a node.js Function and should execute as quickly as possible.

代码

这是在本地node.js中运行的测试工具.一旦运行,我们将其移至Azure函数.

This is the test harness running in local node.js. We'll move this to an Azure Function once it's working.

var express = require('express');
var router = express.Router();
var crypto = require("crypto"); 
var request = require('request');

router.get('/', function (req, res, next) {

  var key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
  var uri = "https://xxxxxx.documents.azure.com";

  var verb = 'GET';
  var type = 'dbs';
  var link = 'dbs';
  var url = `${uri}/${link}`;

  var headers = getDefaultRequestHeaders();

  // var body = `{"query":"SELECT * FROM c", "parameters": []}`;
  var body = '';

  headers['content-length'] = body.length;
  headers['authorization'] = getAuthorizationTokenUsingMasterKey(verb, type, link, headers['x-ms-date'], key);

  request[verb.toLowerCase()]({"url": url, "headers": headers, "body": body}, function (error, response, body) {

    // console.log(`error is ${error}`);
    // console.log(`response is ${JSON.stringify(response, null, 2)}`);
    console.log(`body is ${body}`);

    res.status(response.statusCode).json(body);

  });

});

function getDefaultRequestHeaders(isQuery, date) {

  var headers = {
    "content-type": "application/json", 
    "x-ms-date": new Date().toUTCString(),
    "x-ms-version": "2017-02-22",
    "accept": "application/json",
    "cache-control": "no-cache",
    "user-agent": "xxxxxx/1.0"
  };

  if(isQuery) {
    headers["x-ms-documentdb-isquery"] = true;
    headers["content-type"] = "application/query+json";
  }

  if(date) {
    headers["x-ms-date"] = date;
  }

  return headers;

}

function getAuthorizationTokenUsingMasterKey(verb, resourceType, resourceLink, date, masterKey) {  
    var key = new Buffer(masterKey, "base64");  

    var text = (verb || "").toLowerCase() + "\n" +   
               (resourceType || "").toLowerCase() + "\n" +   
               (resourceLink || "") + "\n" +   
               date.toLowerCase() + "\n" +   
               "" + "\n";  

    var body = new Buffer(text, "utf8");  
    var signature = crypto.createHmac("sha256", key).update(body).digest("base64");  

    var MasterToken = "master";  

    var TokenVersion = "1.0";  

    return encodeURIComponent("type=" + MasterToken + "&ver=" + TokenVersion + "&sig=" + signature);  
}  


module.exports = router;

我们从出于隐私/安全性考虑,密钥,应用名称和用户代理已替换为x.

The key, app name, and user-agent have been replaced with x's for privacy/security.

测试结果

列表数据库

当我尝试对列表数据库进行最基本的调用服务器返回令牌错误:

When I try the most basic call to list dbs the server returns the token error:

  var verb = 'GET';
  var type = 'dbs';
  var link = 'dbs';

响应:

"{\"代码\:\"未经授权\,\"消息\:\"输入的授权令牌无法处理请求.请检查是否根据协议构建了预期的有效负载,并检查所使用的密钥.服务器使用以下有效负载进行签名:'get \ ndbs \ n \ nsat,2017年8月12日12:28:41 gmt \ n \ n'\ r \ nActivityId:acbf19d9-6485-45c5-9c30-6aa21f14d5b3 \}"

"{\"code\":\"Unauthorized\",\"message\":\"The input authorization token can't serve the request. Please check that the expected payload is built as per the protocol, and check the key being used. Server used the following payload to sign: 'get\ndbs\n\nsat, 12 aug 2017 12:28:41 gmt\n\n'\r\nActivityId: acbf19d9-6485-45c5-9c30-6aa21f14d5b3\"}"

获取数据库

但是,当我执行获取数据库请求工作正常:

However, when I perform the get database request it works fine:

  var verb = 'GET';
  var type = 'dbs';
  var link = 'dbs/00001';

响应:

"{\" id \:\" 00001 \,\" _ rid \:\" 0eUiAA == \,\" _ ts \:1441256154,\" _ self \:\" dbs \/0eUiAA == \/\,\" _ etag \:\" \\"00007d4a-0000-0000-0000-0000-55e7d2da0000 \\" \,\" _ colls \:\" colls \/\,\"_users \:\" users \/\}"

"{\"id\":\"00001\",\"_rid\":\"0eUiAA==\",\"_ts\":1441256154,\"_self\":\"dbs\/0eUiAA==\/\",\"_etag\":\"\\"00007d4a-0000-0000-0000-55e7d2da0000\\"\",\"_colls\":\"colls\/\",\"_users\":\"users\/\"}"

列表集合

类似地,从中请求收藏列表该数据库返回令牌错误:

Similarly, requesting the list of collections from this database returns a token error:

var verb = 'GET';
var type = 'colls';
var link = 'dbs/00001/colls';

重新安置:

"{\"代码\:\"未经授权\,\"消息\:\"输入的授权令牌无法处理请求.请检查是否根据协议构建了预期的有效负载,并检查所使用的密钥.服务器使用以下有效负载进行签名:'get \ ncolls \ ndbs/00001 \ nsat,2017年8月12日12:32:19 gmt \ n \ n'\ r \ nActivityId:8a9d4ff8-24ef-4fd2-b400-f9f8aa743572 \}"

"{\"code\":\"Unauthorized\",\"message\":\"The input authorization token can't serve the request. Please check that the expected payload is built as per the protocol, and check the key being used. Server used the following payload to sign: 'get\ncolls\ndbs/00001\nsat, 12 aug 2017 12:32:19 gmt\n\n'\r\nActivityId: 8a9d4ff8-24ef-4fd2-b400-f9f8aa743572\"}"

获取收​​藏集

但是当我致电获取收藏集时,我得到一个有效的答复:

But when I call get collection I get a valid response:

var verb = 'GET';
var type = 'colls';
var link = 'dbs/00001/colls/00001';

响应:

"{\" id \:\" 00001 \,\" indexingPolicy \:{\" indexingMode \:\" consistent \,\" automatic \:true,\" includedPaths \:[{\\ path \:\" \/* \,\" indexes \:[{\" kind \:\" Range \,\" dataType \:\" Number \,\"precision \:-1},{\" kind \:\" Range \,\" dataType \:\" String \,\" precision \:-1},{\" kind \:\"Spatial \",\"dataType \":\"Point \"}]}]],\"excludedPaths \":[]},\"_ rid \":\"0eUiAJMAdQA = \",\"_ ts \":1454200014,\"_ self \":\"dbs \/0eUiAA == \/colls \/0eUiAJMAdQA = \/\",\"_ etag \":\"\\" 00000100-0000-0000-0000-0000-56ad54ce0000 \\"\",\"_ docs \":\"docs \/\",\"_ sprocs \":\"sprocs \/\",\"_ triggers \":\触发器\/\",\"_ udfs\:\" udfs \/\,\" _ conflicts \:\"冲突\/\}"

"{\"id\":\"00001\",\"indexingPolicy\":{\"indexingMode\":\"consistent\",\"automatic\":true,\"includedPaths\":[{\"path\":\"\/*\",\"indexes\":[{\"kind\":\"Range\",\"dataType\":\"Number\",\"precision\":-1},{\"kind\":\"Range\",\"dataType\":\"String\",\"precision\":-1},{\"kind\":\"Spatial\",\"dataType\":\"Point\"}]}],\"excludedPaths\":[]},\"_rid\":\"0eUiAJMAdQA=\",\"_ts\":1454200014,\"_self\":\"dbs\/0eUiAA==\/colls\/0eUiAJMAdQA=\/\",\"_etag\":\"\\"00000100-0000-0000-0000-56ad54ce0000\\"\",\"_docs\":\"docs\/\",\"_sprocs\":\"sprocs\/\",\"_triggers\":\"triggers\/\",\"_udfs\":\"udfs\/\",\"_conflicts\":\"conflicts\/\"}"

列出文档

在该收藏集上请求列出文档这个错误:

Requesting list documents on that collection gives me this error:

var verb = 'GET';
var type = 'docs';
var link = 'dbs/00001/colls/00001/docs';

响应:

"{\"代码\:\"未经授权\,\"消息\:\"输入的授权令牌无法处理请求.请检查是否根据协议构建了预期的有效负载,并检查所使用的密钥.服务器使用以下有效负载进行签名:'get \ ndocs \ ndbs/00001/colls/00001 \ nsat,2017年8月12日12:34:48 gmt \ n \ n'\ r \ nActivityId:57097e95-c41b-4770-b91a-370418ef2cce \}"

"{\"code\":\"Unauthorized\",\"message\":\"The input authorization token can't serve the request. Please check that the expected payload is built as per the protocol, and check the key being used. Server used the following payload to sign: 'get\ndocs\ndbs/00001/colls/00001\nsat, 12 aug 2017 12:34:48 gmt\n\n'\r\nActivityId: 57097e95-c41b-4770-b91a-370418ef2cce\"}"

获取文档

毫不奇怪,获取单个文档工作正常:

Not surprisingly, fetching a single document works fine:

var verb = 'GET';
var type = 'docs';
var link = 'dbs/00001/colls/00001/docs/e7fe638d-2152-2097-f9c6-9801d7cf5cdd';

响应:

"{\" name \:\" test rest api \,\" id \:\" e7fe638d-2152-2097-f9c6-9801d7cf5cdd \,\" _ rid \:\" 0eUiAJMAdQCbHgAAAAAAAA ==\,\" _ self \:\" dbs \/0eUiAA == \/colls \/0eUiAJMAdQA = \/docs \/0eUiAJMAdQCbHgAAAAAAAA == \/\,\" _ etag \:\" \\"0d00d1ee-0000-0000-0000-598ef7d40000 \\"\",\"_ attachments \":\附件\/\",\"_ ts \":1502541779}"

"{\"name\":\"test rest api\",\"id\":\"e7fe638d-2152-2097-f9c6-9801d7cf5cdd\",\"_rid\":\"0eUiAJMAdQCbHgAAAAAAAA==\",\"_self\":\"dbs\/0eUiAA==\/colls\/0eUiAJMAdQA=\/docs\/0eUiAJMAdQCbHgAAAAAAAA==\/\",\"_etag\":\"\\"0d00d1ee-0000-0000-0000-598ef7d40000\\"\",\"_attachments\":\"attachments\/\",\"_ts\":1502541779}"

查询文档

最后,发送查询也会导致令牌错误:

Finally, sending a query also results in a token error:

var verb = 'POST';
var type = 'docs';
var link = 'dbs/00001/colls/00001/docs';
var body = `{"query":"SELECT * FROM c", "parameters": []}`;

响应:

"{\"代码\:\"未经授权\,\"消息\:\"输入的授权令牌无法处理请求.请检查是否根据协议构建了预期的有效负载,并检查所使用的密钥.服务器使用以下有效负载进行签名:'post \ ndocs \ ndbs/00001/colls/00001 \ nsat,2017年8月12日12:35:42 gmt \ n \ n'\ r \ nActivityId:b8b95f8c-1339-423e-b0e7-0d15d3056180 \}"

"{\"code\":\"Unauthorized\",\"message\":\"The input authorization token can't serve the request. Please check that the expected payload is built as per the protocol, and check the key being used. Server used the following payload to sign: 'post\ndocs\ndbs/00001/colls/00001\nsat, 12 aug 2017 12:35:42 gmt\n\n'\r\nActivityId: b8b95f8c-1339-423e-b0e7-0d15d3056180\"}"

推荐答案

我认为文档不正确.在说 resourceLink 的地方,他们实际上应该说 resource id .如果您查看Node SDK代码,这就是他们计算授权标头的方式(注意使用 resourceId ):

I believe the documentation is incorrect. Where they say resourceLink, they should actually say resource id. If you look at the Node SDK code, this is how they are calculating the authorization header (notice the use of resourceId):

getAuthorizationTokenUsingMasterKey: function (verb, resourceId, resourceType, headers, masterKey) {
    var key = new Buffer(masterKey, "base64");

    var text = (verb || "").toLowerCase() + "\n" +
               (resourceType || "").toLowerCase() + "\n" +
               (resourceId || "") + "\n" +
               (headers["x-ms-date"] || "").toLowerCase() + "\n" +
               (headers["date"] || "").toLowerCase() + "\n";

    var body = new Buffer(text, "utf8");

    var signature = crypto.createHmac("sha256", key).update(body).digest("base64");

    var MasterToken = "master";

    var TokenVersion = "1.0";

    return "type=" + MasterToken + "&ver=" + TokenVersion + "&sig=" + signature;
},

因此,如果要列出数据库,因为没有资源ID,则需要为 link 变量使用空字符串.同样,如果要列出数据库中的集合,则链接实际上应该是数据库的ID(例如, dbs/00001 而不是 dbs/00001/colls ).

So if you want to list the databases, because there is no resource id you will need to use an empty string for your link variable. Similarly, if you want to list collections in the database, the link should actually be the id of the database (e.g. dbs/00001 and not dbs/00001/colls).

这篇关于DocumentDB REST API-授权令牌错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆