c# - Cosmos DB Azure 表 API o数据身份验证 REST/C#?

标签 c# rest azure azure-cosmosdb azure-table-storage

我正在尝试使用表 API 访问 Azure Cosmos DB。

挑战是,尽管创建了 SharedKeyLite,服务器仍然返回 Unauthorized - 似乎 SharedKeyLite 不受支持,或者我生成的签名或 header 错误。

这是代码

    static readonly string storageAccountName = "accountName";
    static readonly string storageAccountKey = "xxxx";
    static readonly string uri = "https://accountName.table.cosmosdb.azure.com/Contacts()";
    static readonly string utc_date = DateTime.UtcNow.ToString("r");


    static void Main(string[] args)
    {

        Console.WriteLine(GetResult().Result);

    }


    static async Task<string> GetResult()
    {
        // Set this to whatever payload you desire. Ours is null because 
        //   we're not passing anything in.
        Byte[] requestPayload = null;

        var requestDateString = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
        var requestUri = new Uri(uri);

        DateTime now = DateTime.UtcNow;
        //Instantiate the request message with a null payload.
        using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, uri)
        { Content = (requestPayload == null) ? null : new ByteArrayContent(requestPayload) })
        {

            ConstructHeaders(httpRequestMessage.Headers, requestDateString);

            string authorizationHeader = GenerateSharedKeyLite(storageAccountKey, storageAccountName, uri,requestDateString);
            httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue("SharedKeyLite", authorizationHeader);
            // Send the request.
            using (HttpResponseMessage httpResponseMessage = await new HttpClient().SendAsync(httpRequestMessage))
            {
                string json = await httpResponseMessage.Content.ReadAsStringAsync();
                return json;
            }
        }
    }

这些是我添加的 header ,是 ConstructHeaders 方法的扩展。 请参阅this link for request parameters

     //Construct the headers
    static void ConstructHeaders(HttpRequestHeaders headers, string now)
    {

        headers.Add("x-ms-date", now);
        headers.Add("x-ms-version", "2017-04-17");
        // If you need any additional headers, add them here before creating
        //   the authorization header. 
        headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));


        if (headers.Contains("DataServiceVersion"))
            headers.Remove("DataServiceVersion");
        headers.Add("DataServiceVersion", "3.0;NetFx");
        if (headers.Contains("MaxDataServiceVersion"))
            headers.Remove("MaxDataServiceVersion");
        headers.Add("MaxDataServiceVersion", "3.0;NetFx");
    }

这是创建 SharedKeyLite 的方法

    //Created Shared Key Lite 
    static string GenerateSharedKeyLite(string accessKey, string account, string url, string date)
    {
        var uri = new Uri(url);

        var canonicalizedResourceString = uri.PathAndQuery;
        var queryStart = canonicalizedResourceString.IndexOf('?');
        if (queryStart > -1)
        {
            if (queryStart < canonicalizedResourceString.Length - 1)
            {
                var path = canonicalizedResourceString.Substring(0, queryStart);
                var parameters = HttpUtility.ParseQueryString(canonicalizedResourceString.Substring(queryStart + 1));
                var sb = new StringBuilder();
                foreach (var keyOri in parameters.Keys)
                {
                    var value = parameters[keyOri];
                    var key = keyOri.ToLowerInvariant();
                    sb.Append("\n");
                    sb.Append(key);
                    sb.Append(":");
                    sb.Append(value);
                }
                canonicalizedResourceString = canonicalizedResourceString + sb.ToString();
            }
            else
            {
                canonicalizedResourceString = canonicalizedResourceString.Substring(0, canonicalizedResourceString.Length - 1);
            }
        }
        canonicalizedResourceString = $"/{account}{canonicalizedResourceString}";

        var stringToSign = $"{date}\n{canonicalizedResourceString}";
        var signedSignature = string.Empty;
        using (var hmac = new HMACSHA256(Convert.FromBase64String(accessKey)))
        {
            var outputBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));
            var signature = Convert.ToBase64String(outputBytes);
            return $"{account}:{signature}";
        }


    }

有什么帮助吗?理想情况下,我想使用 simple.odata 执行 odata 查询,但首先尝试使用 HttpClient 来完成这项工作

最佳答案

只需复制您的代码,它就可以在我这边运行。如果您尚未修改代码,请确保您的 storageAccountNamestorageAccountKey 正确无误。

顺便说一句,在方法 GenerateSharedKeyLite 中,不需要向 canonicalizedResourceString 添加查询参数来进行实体操作。如果要操作表或服务的组件信息,只需要添加comp即可。请参阅constructing-the-canonicalized-resource-string

The query string should include the question mark and the comp parameter (for example, ?comp=metadata). No other parameters should be included on the query string.

关于c# - Cosmos DB Azure 表 API o数据身份验证 REST/C#?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51348458/

相关文章:

rest - golang gin-gonic 和包中的拆分文件

css - ImageResizer、azure cdn、缓存清除和 url 重写

c# - 使用 azure 表存储进行分页(升序)

c# - 使用 epplus 将 Excel 保存为电子表格 xml 2003

c# - 将查询字符串数组参数转换为字典值

c# - RSA 读取公钥

c# - 更新很多东西时滞后?新华社

javascript - Angular 8 拦截器 - 如何处理状态 200 的响应

google-app-engine - Google App Engine 中的 JAX-RS 服务

php - 使用 PHP 将消息放入 Azure 队列,并将内容添加到 Blob 存储