【问题标题】:Using REST for CRUD operations in Azure Cosmos DB在 Azure Cosmos DB 中使用 REST 进行 CRUD 操作
【发布时间】:2017-12-05 17:43:14
【问题描述】:

我正在尝试使用 REST 在 Azure Cosmos DB 上执行 CRUD 操作。根据链接- https://docs.microsoft.com/en-us/rest/api/documentdb/create-a-document 我已经创建了我的有效负载并尝试在 Opera 浏览器中使用 Restman 对其进行测试。以下是我的有效载荷详细信息-

标题

Authorization       ***************************

Content-Type        application/query+json

x-ms-date           Tue, 05 Dec 2017 16:49:31 GMT

x-ms-session-token  Session

x-ms-version        2017-02-22

身体

id        sg4c828f-31f8-4db4-8e7c-e8bdff222dsg

value     {     "id": "AndersenFamily",     "LastName": "Andersen",     "Parents": [       {         "FamilyName": null,         "FirstName": "Thomas"       },       {         "FamilyName": null,         "FirstName": "Mary Kay"       }     ],     "Children": [       {         "FamilyName": null,         "FirstName": "Henriette Thaulow",         "Gender": "female",         "Grade": 5,         "Pets": [           {             "GivenName": "Fluffy"           }         ]       }     ],     "Address": {       "State": "WA",       "County": "King",       "City": "Seattle"     },     "IsRegistered": true   }

请求标头中的 auth-token 已使用以下代码在 C# 中生成(根据上述链接中的示例)-

string GenerateAuthToken(string verb, string resourceType, string resourceId, string date, string key, string keyType, string tokenVersion)
{
    var hmacSha256 = new System.Security.Cryptography.HMACSHA256 { Key = Convert.FromBase64String(key) };

    verb = verb ?? "";
    resourceType = resourceType ?? "";
    resourceId = resourceId ?? "";

    string payLoad = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}\n{1}\n{2}\n{3}\n{4}\n",
            verb.ToLowerInvariant(),
            resourceType.ToLowerInvariant(),
            resourceId,
            date.ToLowerInvariant(),
            ""
    );

    byte[] hashPayLoad = hmacSha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(payLoad));
    string signature = Convert.ToBase64String(hashPayLoad);

    return System.Web.HttpUtility.UrlEncode(String.Format(System.Globalization.CultureInfo.InvariantCulture, "type={0}&ver={1}&sig={2}",
        keyType,
        tokenVersion,
        signature));
}

这是传递参数的方式-

GenerateAuthToken("GET", "dbs", "dbs/ToDoList", "Tue, 05 Dec 2017 16:49:31 GMT", PARENT_KEY, "master", "1.0");

所以当我向 URL 发出 POST 请求时-

https://<account_name>.documents.azure.com:<port>/dbs/DCEAAA==/colls/DCEAAIcEVAA=/docs

我得到以下回应-

{ "code": "未授权", "message": "输入的授权令牌不能服务于请求。请检查预期的有效载荷是否按照协议构建, 并检查正在使用的密钥。服务器使用以下有效负载 签名:'post\ndocs\ndceaaicevaa=\ntue,2017 年 12 月 5 日 16:49:31 gmt\n\n'\r\nActivityId: 7565996c-d008-438d-a1e9-744d4871948a, Microsoft.Azure.Documents.Common/1.19.121.4" }

我不知道这里到底出了什么问题。如果有人有任何想法,请告诉我。如有任何澄清,请告诉我。

编辑:在下面添加 Restman 屏幕截图 -

【问题讨论】:

  • 我在这里注意到的一件事是传递给GenerateAuthToken 的参数与您在请求中传递的参数不同。例如,动词在该方法中是 GET,但您实际上是在发出 POST 请求。会不会是这个原因?
  • @GauravMantri 感谢您的回复。实际上这就是我在示例中看到的,我认为它只是用于生成 auth-token。我尝试使用 POST,但这也不起作用。
  • 您能否编辑您的帖子并输入您使用的实际值?
  • @GauravMantri 除了 auth key 和 POST URL 之外的所有其他值都是实际的。
  • 同样,问题是GenerateAuthToken 中的资源类型是dbs,但您请求中的资源类型是docs。请确保提供给此方法的值与您的请求相同。

标签: c# rest azure azure-cosmosdb


【解决方案1】:

我跟进你提到的Document Create Document API,并做一个演示来使用rest API创建documentdb文档。你可以参考一下。对于其他操作,您可以按照以下代码构建哈希令牌。

根据Common Azure Cosmos DB REST request headers,如果我们要创建一个文档,我们需要准备如下的Header

Authorization,x-ms-date,Content-Type,x-ms-version

我们可以从这个document 获得 x-m 版本。最新版本是2017-02-22。

我们可以从document获得你提到的演示代码,关于如何为主令牌构造哈希令牌签名请参考document。从文档中我们可以知道resourceType可能是"dbs", "colls", "docs".我们需要创建一个文档,所以resourceType = docs

var databaseId = "databaseName";
var collectionId = "collectionName";
var datetime = DateTime.UtcNow.ToString("R");
var verb = "post";
var resourceType = "docs"; //
var resourceId = $"dbs/{databaseId}/colls/{collectionId}";
var mastKey = "mastkey value";
var keyType = "master";
var tokenVersion = "1.0";
var authToken = GenerateAuthToken(verb, resourceType, resourceId, datetime, mastKey, keyType, tokenVersion);

我们还需要从上述代码变量datetime中获取x-ms-date值

Post https://{documentDBAccount}.documents.azure.com:443/dbs/{databaseName}/colls/{collectionId}/docs 

更新:

请使用以下数据作为json body

{
    "id": "sg4c828f-31f8-4db4-8e7c-e8bdff222dsg",
    "value": {
        "id": "AndersenFamily",
        "LastName": "Andersen",
        "Parents": [
            {
                "FamilyName": null,
                "FirstName": "Thomas"
            },
            {
                "FamilyName": null,
                "FirstName": "Mary Kay"
            }
        ],
        "Children": [
            {
                "FamilyName": null,
                "FirstName": "Henriette Thaulow",
                "Gender": "female",
                "Grade": 5,
                "Pets": [
                    {
                        "GivenName": "Fluffy"
                    }
                ]
            }
        ],
        "Address": {
            "State": "WA",
            "County": "King",
            "City": "Seattle"
        },
        "IsRegistered": true
    }
}

【讨论】:

  • 嗨。谢谢你。看起来你让它工作了。试用后我会尽快回复您。
  • 我的收藏名称是 ToDoList。如何获取 databaseID 和 collectionID?以及如何构建 POST URL?
  • 好的,我从现有记录的值中找出了 databaseID 和 collectionID - "_self": "dbs/DCEAAA==/colls/DCEAAIcEVAA=/docs/DCEAAIcEVAAHAAAAAAAAAA==/", 所以我的 databaseID 是 DCEAAA== 而 collectionID 是 DCEAAIcEVAA=
  • 我只使用数据库名称和集合名称对其进行测试。您参考屏幕截图的详细信息
  • 我尝试使用数据库名称和集合名称。现在它给出错误 400 错误请求并说请求有效负载无效。
猜你喜欢
  • 2018-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-17
相关资源
最近更新 更多