你当前正在访问 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} 表示令牌类型: master、 resource 或 aad ((如果使用 Azure Cosmos DB RBAC) )。
{tokenversion} 表示令牌的版本,当前为 1.0。
{hashsignature} 表示 哈希令牌 签名或 oauth 令牌 (如果使用 Azure Cosmos DB RBAC)。
应对要添加到 REST 请求中的授权字符串进行编码,以确保其中没有无效的字符。 确保它是使用 MIME RFC2045 进行 Base64 编码的。 此外,哈希签名中使用的主密钥应使用 MIME RFC2045 进行解码,因为它是 Base64 编码的。 如果发现授权的任何问题,请参阅如何 诊断和排查未经授权的异常。
构造主令牌的哈希令牌签名
主密钥令牌的哈希签名可以从以下参数构造: Verb、 ResourceType、 ResourceLink 和 Date。
- 谓词表示请求的 HTTP 谓词。 可能的值包括:get、post、put、patch、delete
注意:值必须为小写。
- 字符串的 ResourceType 部分标识请求所针对的资源类型。 可能的值包括:
- 数据库操作:
dbs
- 容器操作:
colls
- 存储过程:
sprocs
- 用户定义的函数:
udfs
- 触发器:
triggers
- 用户:
users
- 权限:
permissions
- 项级操作:
docs
- 数据库操作:
注意: 值区分大小写,必须为小写。
- 字符串的 ResourceLink 部分是请求定向到的资源的标识属性。
ResourceLink 值取决于你尝试执行的操作。
按照此约定,每个操作都有其自己的相应 ResourceLink:
如果对特定资源执行操作,则该值是指向该资源的链接。 示例:
- 对于获取数据库,请使用:
dbs/{databaseId}
- 对于获取文档,请使用:
dbs/{databaseId}/colls/{containerId}/docs/{docId}
- 对于获取数据库,请使用:
如果对列表、创建、查询 () 的一组资源执行操作,则该值为父资源的链接。 示例:
- 对于“创建文档”,请使用:
dbs/{databaseId}/colls/{containerId}
- 对于“创建存储过程”,请使用:
dbs/{databaseId}/colls/{containerId}
- 对于“创建容器”,请使用:
dbs/{databaseId}
- 对于“创建数据库”,请使用:“”-> 空字符串,因为数据库没有父资源
- 对于“创建文档”,请使用:
注意: 作为 ResourceLink 值的一部分引用的资源名称区分大小写,并且必须与在数据库中声明它们的大小写匹配。 其他组件必须为小写。
字符串的 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 浏览器)生成时间限制的令牌。
此服务器执行以下步骤:
处理新令牌的传入客户端请求。
以特定于应用程序的方式验证客户端标识。
如果客户端成功进行身份验证,它将使用 Cosmos DB 接口 (SDK 或 REST) 生成新的限时令牌,并将其返回给客户端。