【问题标题】:Cosmosdb Resource Token Authorization Header using a REST call使用 REST 调用的 Cosmosdb 资源令牌授权标头
【发布时间】:2018-12-10 03:19:34
【问题描述】:

Cosmosdb 的概念是 permission 对应于 user。该权限包含一个token,可用于在有限的时间内以有限的访问权限访问指定的分区。

我创建了一个资源令牌代理,它创建权限、检索令牌并将其返回给客户端 Xamarin Forms 应用程序。到目前为止一切顺利。

如果我使用来自.NET SDK 的DocumentClient,则该令牌(未经修改)效果很好。

但是,我想避免在我的应用中依赖 DocumentClient,而是直接对 Cosmosdb 进行 REST api 调用。

如果我将 token 放在授权标头中,我会收到该标头的格式错误。我找不到 SDK 的源代码,所有示例都是通过修改主令牌构建的。

谁能解释/指出/举例说明我必须对我从permission 获得的resource token 做些什么以使其成为可接受的标头,以便我可以进行 REST 调用?

TIA

【问题讨论】:

    标签: azure-cosmosdb


    【解决方案1】:

    根据您的描述,我想您已经知道如何获取资源令牌了。除了资源令牌格式之外,您所有的工作都很好。你需要urlencode你的资源令牌然后你的代码就可以了。我测试成功了。

    var databaseId = "db";
    var collectionId = "coll";
    var datetime = DateTime.UtcNow.ToString("R");
    var version = "2017-02-22";
    var resourceId = $"dbs/{databaseId}/colls/{collectionId}";
    var auth = "type%3Dresource%26ver%3D1%26sig%3Dny%2BUlL6QIWR69OfiaSjTsw%3D%3D%3B%2Ba%2FwmK37zLn%2FoilfztnXpfyCN3n9tChunmpBdROF8BH4**********************oU0BJ4z8aDZT%2F%2FgTVJ0hgpXTK8UYMOrL5di3he9wbvQwFkFOdpXD7%2B%2Byhmb1uUOnq%2Fyp454O2fQKR8uA3KaiLCCjYZ6qr%2BQ%2BTV1Cu1u%2F6Yj34nc4UYtpRBX5K************qCGjhvpQ%3D%3D%3B";
    
    var urlPath = $"https://***.documents.azure.com/dbs/db/colls/coll/docs/1";
    Uri uri = new Uri(urlPath);
    HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri);
    HttpClient client = new HttpClient();
    
    client.DefaultRequestHeaders.Add("x-ms-date", datetime);
    client.DefaultRequestHeaders.Add("x-ms-version", version);   
    client.DefaultRequestHeaders.Add("Authorization", auth);
    HttpResponseMessage response = client.SendAsync(request).Result;
    var status = response.IsSuccessStatusCode;
    var message = response.RequestMessage;
    

    【讨论】:

    • 我将其标记为答案,因为没有人真正愿意对此进行尝试,因此杰伊,您就是那个答案。不过,我将尝试在答案中添加更多事实。
    【解决方案2】:

    Jay 的解决方案是正确的。我错过了几个部分。此条目适用于面临相同问题的任何可怜的恶魔。

    1. 正如 Jay 指出的那样,在权限对象中实际从 Cosmosdb 返回的令牌未编码。从 .Net Core 2.x 开始,您需要使用 WebUtility.UrlEncode(token) 来获得正确的格式。我花了一个小时使用HtmlEncode 而不是UrlEncode。我是个白痴。

    {更新:我比原来想象的还要笨。你必须使用HttpUtility.UrlEncode,而不是WebUtility.UrlEncode。这是因为它们的编码方式不同。 WebUtility%3D 之类的东西结束,而 HttpUtility 将其编码为 %3d。这并不重要除非涉及到身份验证令牌。当我在 DocumentClient 调用上运行 Fiddler 时,我注意到令牌包含小写编码值。} 所以忽略上面的 #1 并使用 HttpUtility

    1. 我提到我在原始问题中使用了分区,但 Jay 的回答没有涵盖这一点,所以我仍然失败了。我指定了一个分区键,但从文档中不清楚这是 partition key path 还是 partition key value。如果您认为权限令牌在创建时将包含权限密钥 value,那么这并不明显。没有办法知道幕后发生了什么。反复试验。我个人的最爱。
    2. 但不太明显的问题是分区键的格式。如果您将权限限制为分区,则需要在标头中指定分区,如下所示:

      client.DefaultRequestHeaders.Add("x-ms-documentdb-partitionkey", partitions);

    3. 你需要像这样格式化partitions变量:

      string json = JsonConvert.SerializeObject(new[] { "b39bcd43-8d3d-*********-4e4492fa3e7d" });
      

    那是因为 Cosmodb 期待一个array 的分区键,即使它只接受列表中的分区键(无论如何我都理解)。如果你不想使用JsonConvert,你可以手动构建它,使用$"[\"{yourPartitionKey}\"]"

    毕竟它像桃子一样工作。再次感谢杰!

    【讨论】:

    • 看来我的回答很不完善。非常感谢您的分享!
    • 不,伙计,这很棒。我真的很挣扎,甚至可能而且错误代码根本没有帮助。你向我证明这是可以做到的,这打破了僵局。
    猜你喜欢
    • 2019-05-07
    • 2019-05-23
    • 2015-05-26
    • 2013-09-03
    • 1970-01-01
    • 2017-11-06
    • 2021-04-15
    • 2017-03-10
    • 1970-01-01
    相关资源
    最近更新 更多