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

查看:18
本文介绍了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.

背景

我们已经成功使用带有 DocumentDB 的 node.js sdk 一年多了,但是由于我们想将后端的 restful API 代码从 node.js 应用服务迁移到 Azure Functions,我们看到 10-30第二个延迟时间开始发挥作用,因为在一段时间内没有调用函数时 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,它需要零个外部库才能在 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() + "
" +   
               (resourceType || "").toLowerCase() + "
" +   
               (resourceLink || "") + "
" +   
               date.toLowerCase() + "
" +   
               "" + "
";  

    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;

我们正在逐字使用 DocumentDB API 页面中的访问控制.

We are using the getAuthorizationTokenFromMasterKey function verbatim from the Access control in the DocumentDB API page.

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

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

测试结果

列出数据库

当我尝试对 list dbs 服务器返回令牌错误:

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';

回复:

"{"code":"Unauthorized","message":"输入的授权令牌不能服务于请求.请检查预期的有效负载是否按照协议构建,并检查正在使用的密钥.服务器使用以下负载进行签名:'get dbs sat, 12 aug 2017 12:28:41 gmt ' ActivityId: 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 dbs sat, 12 aug 2017 12:28:41 gmt ' ActivityId: 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-55e7d2da0000\"","_colls":"colls/","_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';

回复:

"{"code":"Unauthorized","message":"输入的授权令牌不能服务于请求.请检查预期的有效负载是否按照协议构建,并检查正在使用的密钥.服务器使用以下负载进行签名:'get colls dbs/00001 sat, 2017 年 8 月 12 日 12:32:19 gmt ' ActivityId: 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 colls dbs/00001 sat, 12 aug 2017 12:32:19 gmt ' ActivityId: 8a9d4ff8-24ef-4fd2-b400-f9f8aa743572"}"

获取收​​藏

但是当我调用 get collection我得到了有效的回复:

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","精度":-1},{"种类":"范围","数据类型":"字符串","精度":-1},{"种类":"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/"}"

"{"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';

回复:

"{"code":"Unauthorized","message":"输入的授权令牌不能服务于请求.请检查预期的有效负载是否按照协议构建,并检查正在使用的密钥.服务器使用以下负载进行签名:'get docs dbs/00001/colls/00001 sat, 2017 年 8 月 12 日 12:34:48 gmt ' ActivityId: 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 docs dbs/00001/colls/00001 sat, 12 aug 2017 12:34:48 gmt ' ActivityId: 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":"0eUiAJMAdQCbHgAAAAAAA==","_self":"dbs/0eUiAA==/colls/0eUiAJMAdQA=/docs/0eUiAJMAdQCbHgAAAAAAA==/","_etag":"\"0d00d1ee-0000-0000-0000-598ef7d40000\"","_attachments":"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": []}`;

回复:

"{"code":"Unauthorized","message":"输入的授权令牌不能服务于请求.请检查预期的有效负载是否按照协议构建,并检查正在使用的密钥.服务器使用以下负载进行签名:'post docs dbs/00001/colls/00001 sat, 2017 年 8 月 12 日 12:35:42 gmt ' ActivityId: 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 docs dbs/00001/colls/00001 sat, 12 aug 2017 12:35:42 gmt ' ActivityId: 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() + "
" +
               (resourceType || "").toLowerCase() + "
" +
               (resourceId || "") + "
" +
               (headers["x-ms-date"] || "").toLowerCase() + "
" +
               (headers["date"] || "").toLowerCase() + "
";

    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天全站免登陆