401(未经授权)尝试通过REST API查询DocumentDb时

时间:2016-02-15 17:19:37

标签: azure-cosmosdb

我想对我的Azure DocumentDb进行SQL查询。我现在有一个非常混乱的代码,但它看起来像是

public string GetResources(string collection) {
    var client = new System.Net.Http.HttpClient();
    client.DefaultRequestHeaders.Add("x-ms-date", utc_date);
    client.DefaultRequestHeaders.Add("x-ms-version", "2015-08-06");
    client.DefaultRequestHeaders.Add("x-ms-documentdb-isquery", "True");
    client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/query+json"));

    //GET a document
    var verb = "POST";
    var resourceType = "docs";
    var resourceLink = string.Format("dbs/{0}/colls/{1}/docs", databaseId, collection);
    var resourceId = (idBased) ? resourceLink : "";

    var authHeader = GenerateAuthToken(verb, resourceId, resourceType, masterKey, "master", "1.0");
    Console.WriteLine(authHeader);

    client.DefaultRequestHeaders.Remove("authorization");
    client.DefaultRequestHeaders.Add("authorization", authHeader);


    var q = new DbQuery {
        Query = "SELECT * FROM root"
    };
    var postData = new List<KeyValuePair<string, string>>();
    postData.Add(new KeyValuePair<string, string>("query", q.Query));
    return PostAsync(resourceLink, postData, client).Result;
}


public async Task<string> PostAsync(string uri, List<KeyValuePair<string, string>> data, HttpClient httpClient)
{
    var content = new FormUrlEncodedContent(data);
    Console.WriteLine(httpClient.DefaultRequestHeaders.Authorization);
    var response = await httpClient.PostAsync(new Uri(baseUri, uri), content);

    response.EnsureSuccessStatusCode();

    string postContent = await response.Content.ReadAsStringAsync();
    return await Task.Run(() => postContent);
}

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

    string verbInput = verb ?? "";
    string resourceIdInput = resourceId ?? "";
    string resourceTypeInput = resourceType ?? "";

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

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

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

我有一个请求通过其ID获取文档,我使用相同的方法。它工作正常。我相信问题可能出在我的resourceLink上,但说实话,我尝试了很多版本而且没有结果......我在这里错过了什么?

2 个答案:

答案 0 :(得分:2)

resourceLink的值取决于您使用的是基于ID的路由还是基于路由的路由。

看起来您正在使用基于ID的路由 所以,对于查询,resourceLink应该是

string.Format("dbs/{0}/colls/{1}/docs", databaseId, collectionId);

和resourceId应该相同,

string.Format("dbs/{0}/colls/{1}", databaseId, collectionId)

POST有点不同,因为它需要设置特定的标头。 使用REST API查询DocumentDB资源的REST文档应记录所需内容 - https://msdn.microsoft.com/en-us/library/azure/dn783363.aspx

有关resourceLink&amp;的更多示例resourceId和一个工作eample看看我们刚刚发布的.NET示例中的REST。 https://github.com/Azure/azure-documentdb-dotnet/blob/d3f8e9c731bc92816d023719e7e780b7a9546ca2/samples/rest-from-.net/Program.cs#L151-L164

答案 1 :(得分:1)

对于POST我使用这样的东西:

var resourceLink = string.Format("dbs/{0}/colls/{1}", DataBaseName, DocumentCollectionName);
using (var client = GetClient(
            "POST", 
            resourceLink,
            "docs", 
            PrimaryKey))
{
      try
      {
            var content = 
                    new StringContent("{\"query\":\"SELECT * FROM root\"}", Encoding.UTF8, "application/query+json");
                content.Headers.ContentType.CharSet = "";
            var r = client.PostAsync(
                new Uri(
                    new Uri(EndpointUri), resourceLink + "/docs"), content).Result;
            }
            catch (Exception ex)
            {
            }
        }}

它对我有用