DocumentDB - 访问控制
DocumentDB 提供了控制对 DocumentDB 资源的访问的概念。 对 DocumentDB 资源的访问由主密钥令牌或资源令牌控制。 基于资源令牌的连接只能访问该令牌指定的资源,不能访问其他资源。 资源令牌基于用户权限。
首先,您创建一个或多个用户,这些用户是在数据库级别定义的。
然后,根据您希望允许每个用户访问的资源,为每个用户创建一个或多个权限。
每个权限都会生成一个资源令牌,该令牌允许对给定资源进行只读或完全访问,并且可以是数据库中的任何用户资源。
用户在数据库级别定义,并为每个用户定义权限。
用户和权限适用于数据库中的所有集合。
让我们看一个简单的示例,在该示例中我们将了解如何定义用户和权限以在 DocumentDB 中实现精细的安全性。
我们将从一个新的 DocumentClient 开始并查询 myfirstdb 数据库。
private static async Task CreateDocumentClient() { // Create a new instance of the DocumentClient using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) { database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id = 'myfirstdb'").AsEnumerable().First(); collection = client.CreateDocumentCollectionQuery(database.CollectionsLink, "SELECT * FROM c WHERE c.id = 'MyCollection'").AsEnumerable().First(); var alice = await CreateUser(client, "Alice"); var tom = await CreateUser(client, "Tom"); } }
以下是 CreateUser 的实现。
private async static Task<User> CreateUser(DocumentClient client, string userId) { Console.WriteLine(); Console.WriteLine("**** Create User {0} in {1} ****", userId, database.Id); var userDefinition = new User { Id = userId }; var result = await client.CreateUserAsync(database.SelfLink, userDefinition); var user = result.Resource; Console.WriteLine("Created new user"); ViewUser(user); return user; }
步骤 1 − 创建两个用户,Alice 和 Tom,就像我们创建的任何资源一样,我们使用所需的 Id 构造一个定义对象并调用 create 方法,在本例中,我们使用数据库的 SelfLink 和 userDefinition 调用 CreateUserAsync。 我们从新创建的用户对象的资源属性中获取结果。
现在在数据库中查看这两个新用户。
private static void ViewUsers(DocumentClient client) { Console.WriteLine(); Console.WriteLine("**** View Users in {0} ****", database.Id); var users = client.CreateUserQuery(database.UsersLink).ToList(); var i = 0; foreach (var user in users) { i++; Console.WriteLine(); Console.WriteLine("User #{0}", i); ViewUser(user); } Console.WriteLine(); Console.WriteLine("Total users in database {0}: {1}", database.Id, users.Count); } private static void ViewUser(User user) { Console.WriteLine("User ID: {0} ", user.Id); Console.WriteLine("Resource ID: {0} ", user.ResourceId); Console.WriteLine("Self Link: {0} ", user.SelfLink); Console.WriteLine("Permissions Link: {0} ", user.PermissionsLink); Console.WriteLine("Timestamp: {0} ", user.Timestamp); }
步骤 2 − 针对数据库的 UsersLink 调用 CreateUserQuery 以检索所有用户的列表。 然后循环遍历它们并查看它们的属性。
现在我们必须先创建它们。 假设我们希望允许 Alice 对 MyCollection 集合具有读/写权限,但 Tom 只能读取该集合中的文档。
await CreatePermission(client, alice, "Alice Collection Access", PermissionMode.All, collection); await CreatePermission(client, tom, "Tom Collection Access", PermissionMode.Read, collection);
Step 3− 对 MyCollection 集合的资源创建权限,因此我们需要为该资源获取 SelfLink。
步骤 4 − 然后为 Alice 创建一个 Permission.All 在此集合上,为 Tom 创建一个 Permission.Read 在此集合上。
以下是 CreatePermission 的实现。
private async static Task CreatePermission(DocumentClient client, User user, string permId, PermissionMode permissionMode, string resourceLink) { Console.WriteLine(); Console.WriteLine("**** Create Permission {0} for {1} ****", permId, user.Id); var permDefinition = new Permission { Id = permId, PermissionMode = permissionMode, ResourceLink = resourceLink }; var result = await client.CreatePermissionAsync(user.SelfLink, permDefinition); var perm = result.Resource; Console.WriteLine("Created new permission"); ViewPermission(perm); }
正如您现在所期望的那样,我们通过为新权限创建一个定义对象来实现此目的,其中包括 Id 和 PermissionMode,它是 Permission.All 或 Permission.Read,以及受权限保护的资源的 SelfLink。
步骤 5 − 调用CreatePermissionAsync并从结果中的资源属性中获取创建的权限。
查看创建的权限,下面是ViewPermissions的实现。
private static void ViewPermissions(DocumentClient client, User user) { Console.WriteLine(); Console.WriteLine("**** View Permissions for {0} ****", user.Id); var perms = client.CreatePermissionQuery(user.PermissionsLink).ToList(); var i = 0; foreach (var perm in perms) { i++; Console.WriteLine(); Console.WriteLine("Permission #{0}", i); ViewPermission(perm); } Console.WriteLine(); Console.WriteLine("Total permissions for {0}: {1}", user.Id, perms.Count); } private static void ViewPermission(Permission perm) { Console.WriteLine("Permission ID: {0} ", perm.Id); Console.WriteLine("Resource ID: {0} ", perm.ResourceId); Console.WriteLine("Permission Mode: {0} ", perm.PermissionMode); Console.WriteLine("Token: {0} ", perm.Token); Console.WriteLine("Timestamp: {0} ", perm.Timestamp); }
这一次,这是针对用户权限链接的权限查询,我们只是列出为用户返回的每个权限。
让我们删除 Alice 和 Tom 的权限。
await DeletePermission(client, alice, "Alice Collection Access"); await DeletePermission(client, tom, "Tom Collection Access");
以下是DeletePermission的实现。
private async static Task DeletePermission(DocumentClient client, User user, string permId) { Console.WriteLine(); Console.WriteLine("**** Delete Permission {0} from {1} ****", permId, user.Id); var query = new SqlQuerySpec { QueryText = "SELECT * FROM c WHERE c.id = @id", Parameters = new SqlParameterCollection { new SqlParameter { Name = "@id", Value = permId } } }; Permission perm = client.CreatePermissionQuery(user.PermissionsLink, query) .AsEnumerable().First(); await client.DeletePermissionAsync(perm.SelfLink); Console.WriteLine("Deleted permission {0} from user {1}", permId, user.Id); }
步骤 6 − 如需删除权限,请通过权限Id查询SelfLink,然后使用SelfLink删除权限。
接下来,让我们删除用户本身。 让我们删除这两个用户。
await DeleteUser(client, "Alice"); await DeleteUser(client, "Tom");
以下是DeleteUser的实现。
private async static Task DeleteUser(DocumentClient client, string userId) { Console.WriteLine(); Console.WriteLine("**** Delete User {0} in {1} ****", userId, database.Id); var query = new SqlQuerySpec { QueryText = "SELECT * FROM c WHERE c.id = @id", Parameters = new SqlParameterCollection { new SqlParameter { Name = "@id", Value = userId } } }; User user = client.CreateUserQuery(database.SelfLink, query).AsEnumerable().First(); await client.DeleteUserAsync(user.SelfLink); Console.WriteLine("Deleted user {0} from database {1}", userId, database.Id); }
步骤 7 − 首先查询获取她的 SelfLink,然后调用 DeleteUserAsync 删除她的用户对象。
以下是CreateDocumentClient任务的实现,其中我们调用了上述所有任务。
private static async Task CreateDocumentClient() { // Create a new instance of the DocumentClient using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) { database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id = 'myfirstdb'").AsEnumerable().First(); collection = client.CreateDocumentCollectionQuery(database.CollectionsLink, "SELECT * FROM c WHERE c.id = 'MyCollection'").AsEnumerable().First(); ViewUsers(client); var alice = await CreateUser(client, "Alice"); var tom = await CreateUser(client, "Tom"); ViewUsers(client); ViewPermissions(client, alice); ViewPermissions(client, tom); string collectionLink = client.CreateDocumentCollectionQuery(database.SelfLink, "SELECT VALUE c._self FROM c WHERE c.id = 'MyCollection'") .AsEnumerable().First().Value; await CreatePermission(client, alice, "Alice Collection Access", PermissionMode.All, collectionLink); await CreatePermission(client, tom, "Tom Collection Access", PermissionMode.Read, collectionLink); ViewPermissions(client, alice); ViewPermissions(client, tom); await DeletePermission(client, alice, "Alice Collection Access"); await DeletePermission(client, tom, "Tom Collection Access"); await DeleteUser(client, "Alice"); await DeleteUser(client, "Tom"); } }
编译并执行上述代码后,您将收到以下输出。
**** View Users in myfirstdb **** Total users in database myfirstdb: 0 **** Create User Alice in myfirstdb **** Created new user User ID: Alice Resource ID: kV5oAC56NwA= Self Link: dbs/kV5oAA==/users/kV5oAC56NwA=/ Permissions Link: dbs/kV5oAA==/users/kV5oAC56NwA=/permissions/ Timestamp: 12/17/2015 5:44:19 PM **** Create User Tom in myfirstdb **** Created new user User ID: Tom Resource ID: kV5oAALxKgA= Self Link: dbs/kV5oAA==/users/kV5oAALxKgA=/ Permissions Link: dbs/kV5oAA==/users/kV5oAALxKgA=/permissions/ Timestamp: 12/17/2015 5:44:21 PM **** View Users in myfirstdb **** User #1 User ID: Tom Resource ID: kV5oAALxKgA= Self Link: dbs/kV5oAA==/users/kV5oAALxKgA=/ Permissions Link: dbs/kV5oAA==/users/kV5oAALxKgA=/permissions/ Timestamp: 12/17/2015 5:44:21 PM User #2 User ID: Alice Resource ID: kV5oAC56NwA= Self Link: dbs/kV5oAA==/users/kV5oAC56NwA=/ Permissions Link: dbs/kV5oAA==/users/kV5oAC56NwA=/permissions/ Timestamp: 12/17/2015 5:44:19 PM Total users in database myfirstdb: 2 **** View Permissions for Alice **** Total permissions for Alice: 0 **** View Permissions for Tom **** Total permissions for Tom: 0 **** Create Permission Alice Collection Access for Alice **** Created new permission Permission ID: Alice Collection Access Resource ID: kV5oAC56NwDON1RduEoCAA== Permission Mode: All Token: type=resource&ver=1&sig=zB6hfvvleC0oGGbq5cc67w==;Zt3Lx Ol14h8pd6/tyF1h62zbZKk9VwEIATIldw4ZyipQGW951kirueAKdeb3MxzQ7eCvDfvp7Y/ZxFpnip/D G JYcPyim5cf+dgLvos6fUuiKSFSul7uEKqp5JmJqUCyAvD7w+qt1Qr1PmrJDyAIgbZDBFWGe2VT9FaBH o PYwrLjRlnH0AxfbrR+T/UpWMSSHtLB8JvNFZNSH8hRjmQupuTSxCTYEC89bZ/pS6fNmNg8=; Timestamp: 12/17/2015 5:44:28 PM **** Create Permission Tom Collection Access for Tom **** Created new permission Permission ID: Tom Collection Access Resource ID: kV5oAALxKgCMai3JKWdfAA== Permission Mode: Read Token: type=resource&ver=1&sig=ieBHKeyi6EY9ZOovDpe76w==;92gwq V4AxKaCJ2dLS02VnJiig/5AEbPcfo1xvOjR10uK3a3FUMFULgsaK8nzxdz6hLVCIKUj6hvMOTOSN8Lt 7 i30mVqzpzCfe7JO3TYSJEI9D0/5HbMIEgaNJiCu0JPPwsjVecTytiLN56FHPguoQZ7WmUAhVTA0IMP6 p jQpLDgJ43ZaG4Zv3qWJiO689balD+egwiU2b7RICH4j6R66UVye+GPxq/gjzqbHwx79t54=; Timestamp: 12/17/2015 5:44:30 PM **** View Permissions for Alice **** Permission #1 Permission ID: Alice Collection Access Resource ID: kV5oAC56NwDON1RduEoCAA== Permission Mode: All Token: type=resource&ver=1&sig=BSzz/VNe9j4IPJ9M31Mf4Q==;Tcq/B X50njB1vmANZ/4aHj/3xNkghaqh1OfV95JMi6j4v7fkU+gyWe3mJasO3MJcoop9ixmVnB+RKOhFaSxE l P37SaGuIIik7GAWS+dcEBWglMefc95L2YkeNuZsjmmW5b+a8ELCUg7N45MKbpzkp5BrmmGVJ7h4Z4pf D rdmehYLuxSPLkr9ndbOOrD8E3bux6TgXCsgYQscpIlJHSKCKHUHfXWBP2Y1LV2zpJmRjis=; Timestamp: 12/17/2015 5:44:28 PM Total permissions for Alice: 1 **** View Permissions for Tom **** Permission #1 Permission ID: Tom Collection Access Resource ID: kV5oAALxKgCMai3JKWdfAA== Permission Mode: Read Token: type=resource&ver=1&sig=NPkWNJp1mAkCASE8KdR6PA==;ur/G2 V+fDamBmzECux000VnF5i28f8WRbPwEPxD1DMpFPqYcu45wlDyzT5A5gBr3/R3qqYkEVn8bU+een6Gl j L6vXzIwsZfL12u/1hW4mJT2as2PWH3eadry6Q/zRXHAxV8m+YuxSzlZPjBFyJ4Oi30mrTXbBAEafZhA 5 yvbHkpLmQkLCERy40FbIFOzG87ypljREpwWTKC/z8RSrsjITjAlfD/hVDoOyNJwX3HRaz4=; Timestamp: 12/17/2015 5:44:30 PM Total permissions for Tom: 1 **** Delete Permission Alice Collection Access from Alice **** Deleted permission Alice Collection Access from user Alice **** Delete Permission Tom Collection Access from Tom **** Deleted permission Tom Collection Access from user Tom **** Delete User Alice in myfirstdb **** Deleted user Alice from database myfirstdb **** Delete User Tom in myfirstdb **** Deleted user Tom from database myfirstdb