你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

Azure Cosmos DB SQL API 中的访问控制

Azure Cosmos DB 是一个完全托管的 NoSQL 数据库服务,用于新式应用开发。 本文介绍了适用于 Azure Cosmos DB 的 SQL API。 对 SQL API 中资源的访问由主密钥令牌或资源令牌控制。 若要访问资源,所选令牌应作为授权字符串的一部分包含在 REST 授权标头中。

主密钥令牌

主密钥令牌是允许用户完全控制特定帐户中的 Cosmos DB 资源的所有访问密钥令牌。 主密钥是在创建帐户过程中创建的。 有两组主密钥:主要密钥和辅助密钥。 然后,帐户管理员可以使用辅助密钥执行密钥轮换。 此外,帐户管理员还可以根据需要重新生成密钥。 有关重新生成和滚动密钥的说明,请参阅 保护对 Azure Cosmos DB 中的数据的访问

资源令牌

为数据库中的用户设置访问权限,以便对资源(也称为权限资源)进行精确的访问控制时,会创建资源令牌。 权限资源包含一个哈希资源令牌,该令牌使用用户有权访问的资源路径和访问类型的相关信息构造。 权限资源令牌有时间限制,并且其有效期可被重写。 对权限资源执行操作(POST、GET、PUT)时,将生成新的资源令牌。 有关权限和资源令牌的信息,请参阅 Cosmos DB 权限上的操作

授权标头

所有 REST 操作(无论是使用主密钥令牌还是资源令牌)都必须包含授权标头和授权字符串,以便与资源交互。 授权字符串采用以下格式:

type={typeoftoken}&ver={tokenversion}&sig={hashsignature}  

授权字符串如以下示例所示:

type=master&ver=1.0&sig=5mDuQBYA0kb70WDJoTUzSBMTG3owkC0/cEN4fqa18/s=  

括号中的部分如下所示:

  • {typeoftoken} 表示令牌类型: masterresourceaad ((如果使用 Azure Cosmos DB RBAC) )。

  • {tokenversion} 表示令牌的版本,当前为 1.0

  • {hashsignature} 表示 哈希令牌 签名或 oauth 令牌 (如果使用 Azure Cosmos DB RBAC)。

应对要添加到 REST 请求中的授权字符串进行编码,以确保其中没有无效的字符。 确保它是使用 MIME RFC2045 进行 Base64 编码的。 此外,哈希签名中使用的主密钥应使用 MIME RFC2045 进行解码,因为它是 Base64 编码的。 如果发现授权的任何问题,请参阅如何 诊断和排查未经授权的异常。

构造主令牌的哈希令牌签名

主密钥令牌的哈希签名可以从以下参数构造: VerbResourceTypeResourceLinkDate

  1. 谓词表示请求的 HTTP 谓词。 可能的值包括:get、post、put、patch、delete

注意:值必须为小写。

  1. 字符串的 ResourceType 部分标识请求所针对的资源类型。 可能的值包括:
    • 数据库操作: dbs
    • 容器操作: colls
    • 存储过程: sprocs
    • 用户定义的函数: udfs
    • 触发器: triggers
    • 用户: users
    • 权限: permissions
    • 项级操作: docs

注意: 值区分大小写,必须为小写。

  1. 字符串的 ResourceLink 部分是请求定向到的资源的标识属性。 ResourceLink 值取决于你尝试执行的操作。 按照此约定,每个操作都有其自己的相应 ResourceLink:
    • 如果对特定资源执行操作,则该值是指向该资源的链接。 示例:

      • 对于获取数据库,请使用: dbs/{databaseId}
      • 对于获取文档,请使用: dbs/{databaseId}/colls/{containerId}/docs/{docId}
    • 如果对列表、创建、查询 () 的一组资源执行操作,则该值为父资源的链接。 示例:

      • 对于“创建文档”,请使用: dbs/{databaseId}/colls/{containerId}
      • 对于“创建存储过程”,请使用: dbs/{databaseId}/colls/{containerId}
      • 对于“创建容器”,请使用: dbs/{databaseId}
      • 对于“创建数据库”,请使用:“”-> 空字符串,因为数据库没有父资源

注意: 作为 ResourceLink 值的一部分引用的资源名称区分大小写,并且必须与在数据库中声明它们的大小写匹配。 其他组件必须为小写。

  1. 字符串的 Date 部分是发送消息的 UTC 日期和时间, (RFC 7231 日期/时间格式) 定义的“HTTP-date”格式,例如“Tue, 01 Nov 1994 08:12:31 GMT”。

    在 C# 中,可以通过对 值使用“R”格式说明符 DateTime.UtcNow 来获取它。

    此同一日期 (格式相同,) 也需要在请求中作为 x-ms-date 标头传递。

注意: 该值区分大小写,并且必须全部为小写。

为了计算签名,我们使用基于 SHA256 的基于哈希的消息身份验证代码 (HMAC) 函数,并将 CosmosDB 密钥用作机密。

哈希函数的有效负载基于上面使用以下格式的 4 个组件: "{verb}\n{resourceType}\n{resourceLink}\n{date}\n\n" (记下有效负载) 末尾的额外新行。

构造调用的 Authorization 标头时,函数的 Base64 编码结果将用作签名。

有效 Authorization 标头的示例 [C#] :

    httpClient.DefaultRequestHeaders.Clear();
    httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
    httpClient.DefaultRequestHeaders.Add("authorization", auth); //generated using method below
    httpClient.DefaultRequestHeaders.Add("x-ms-date", requestDateString);
    httpClient.DefaultRequestHeaders.Add("x-ms-version", "2018-12-31");

生成有效授权签名的示例 [C#] 方法:

若要查看 Cosmos DB REST API 的完整示例,请访问 GitHub 上的 Cosmos DB REST API 示例存储库

  
string GenerateMasterKeyAuthorizationSignature(HttpMethod verb, ResourceType resourceType, string resourceLink, string date, string key)
{
    var keyType = "master";
    var tokenVersion = "1.0";
    var payload = $"{verb.ToString().ToLowerInvariant()}\n{resourceType.ToString().ToLowerInvariant()}\n{resourceLink}\n{date.ToLowerInvariant()}\n\n";

    var hmacSha256 = new System.Security.Cryptography.HMACSHA256 { Key = Convert.FromBase64String(key) };
    var hashPayload = hmacSha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(payload));
    var signature = Convert.ToBase64String(hashPayload);
    var authSet = WebUtility.UrlEncode($"type={keyType}&ver={tokenVersion}&sig={signature}");

    return authSet;
}
  

示例 [Node.js]:

  
var crypto = require("crypto");  
  
function getAuthorizationTokenUsingMasterKey(verb, resourceType, resourceId, date, masterKey) {  
    var key = new Buffer(masterKey, "base64");  
  
    var text = (verb || "").toLowerCase() + "\n" +   
               (resourceType || "").toLowerCase() + "\n" +   
               (resourceId || "") + "\n" +   
               date.toLowerCase() + "\n" +   
               "" + "\n";  
  
    var body = new Buffer(text, "utf8");  
    var signature = crypto.createHmac("sha256", key).update(body).digest("base64");  
  
    var MasterToken = "master";  
  
    var TokenVersion = "1.0";  
  
    return encodeURIComponent("type=" + MasterToken + "&ver=" + TokenVersion + "&sig=" + signature);  
}  
  

示例编码:

参数
谓词 GET
资源类型 “dbs”
资源链接 “dbs/ToDoList”
日期 2017年4月27日星期四 00:51:12 GMT
密钥 dsZQi3KtZmCv1ljt3VNWNm7sQUF1y5rJfC6kv5Jiwv
W0EndXdDku/dkKBp8/ufDToSxLzR4y+O/0H/t4bQtVNw==
键类型
令牌版本 1.0
输出授权字符串 type%3dmaster%26ver%3d1.0%26sig%3dc09PEVJr
gp2uQRkr934kFbTqhByc7TVr3OHyqlu%2bc%2bc%3d

构造资源令牌的哈希签名

资源令牌必须由中间服务器生成。 服务器充当主密钥保护者,并为不受信任的客户端(如 Web 浏览器)生成时间限制的令牌。

此服务器执行以下步骤:

  1. 处理新令牌的传入客户端请求。

  2. 以特定于应用程序的方式验证客户端标识。

  3. 如果客户端成功进行身份验证,它将使用 Cosmos DB 接口 (SDK 或 REST) 生成新的限时令牌,并将其返回给客户端。

另请参阅