.net - 通过 REST 在 DocumentDb 中创建文档时未经授权

标签 .net rest azure azure-cosmosdb .net-core

我使用的是 .NET Core,因此无法使用 Azure DocumentDb SDK。这就是为什么我想通过 REST 接口(interface)创建文档。我已设法查询数据库,但当我发布 JSON 文档时,我收到未经授权的响应。这是我的代码:

const string DatabaseId = "DB-id";
const string CollectionId = "UserSettings";
var documentDbUrl = "Injected via DI";
var authorizationKey = "Also injected;

using (var httpClient = new HttpClient())
{
    var utcNow = DateTime.UtcNow;
    httpClient.DefaultRequestHeaders.Add("x-ms-date", utcNow.ToString("r"));
    httpClient.DefaultRequestHeaders.Add("x-ms-version", "2015-08-06");
    httpClient.DefaultRequestHeaders.Add("x-ms-documentdb-is-upsert", "true");

    var resourceLink = string.Format("dbs/{0}/colls/{1}/docs", DatabaseId, CollectionId);
    var baseUrl = new Uri(documentDbUrl);

    var masterKeyAuthorizationSignatureGenerator = new MasterKeyAuthorizationSignatureGenerator();
    var authHeader = masterKeyAuthorizationSignatureGenerator.Generate("POST", resourceLink, "docs", authorizationKey, "master", "1.0", utcNow);
    httpClient.DefaultRequestHeaders.Add("authorization", authHeader);

    var response = await httpClient.PostAsJsonAsync(new Uri(baseUrl, resourceLink), userSettings);

    // at this point, response.StatusCode is Unauthorized
}

您看到的MasterKeyAuthorizationSignatureGenerator包含the logic to create the hash ,在查询数据库时有效:

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

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

    var hashPayLoad = hmacSha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(payLoad));
    var signature = Convert.ToBase64String(hashPayLoad);

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

我确信databaseid、collectionid、url 和key 是正确的。 key 和 id 与我用来查询的相同,有效。当我更改 url 时,例如通过添加 documentid(然后我自己生成),我会收到另一条消息 (MethodNotAllowed)。

更新:

使用 Postman,我可以看到这是我得到的响应:

{
    "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\ndocs\ndbs/MyDb/colls/MyColl\nsat, 23 apr 2016 09:44:39 gmt\n\n'\r\nActivityId: 1be76530-ad32-4b54-b96b-6e0d4ebbc851"
}

关于我做错了什么或者我如何分析这个问题有任何提示吗?

最佳答案

请注意,有两种方法可以在 URI 中指定资源:

1) using the resource id.  The id is user settable.

2) using the resource _rid.  This is the system generated id for the resource.

使用资源 ID(方法 1)时,必须确保用于散列签名 token 的连接 token 中的资源 ID 与资源中使用的大小写相同,因为资源 ID 区分大小写。例如,如果集合的资源 id 是 MyCollection,则资源 id 应该恰好是串联 token 中的 MyCollection。

本文提供了构建哈希签名 token 的更多详细信息。 https://msdn.microsoft.com/en-us/library/azure/dn783368.aspx

关于.net - 通过 REST 在 DocumentDb 中创建文档时未经授权,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36752148/

相关文章:

jquery - 将复杂对象传递到 WCF Rest 服务

bash - 为什么对 REST 服务的 bash/CURL 调用会给出与参数不一致的结果?

azure - 从 Windows 桌面应用程序调用具有 AD 授权的 Azure Function

azure - KQL 条件子查询

c# - Azure 上的 WCF 与 STS

.net - google mail如何用html5实现新的上传功能?

c# - P/调用第三方弹窗

c# - 使用 DataContractSerializer 时设置属性的初始值

.net - SQL Server SMO 从远程服务器本地备份

java - 使用 PATCH 和 Jersey Client API 进行单元测试