Banco de Dados de Documentos - Controle de Acesso

DocumentDB fornece os conceitos para controlar o acesso aos recursos do DocumentDB. O acesso aos recursos do Banco de Dados de Documentos é controlado por um token de chave mestra ou um token de recurso. As conexões baseadas em tokens de recursos podem acessar apenas os recursos especificados pelos tokens e nenhum outro recurso. Os tokens de recursos são baseados nas permissões do usuário.

  • Primeiro, você cria um ou mais usuários, e eles são definidos no nível do banco de dados.

  • Em seguida, você cria uma ou mais permissões para cada usuário, com base nos recursos que deseja permitir que cada usuário acesse.

  • Cada permissão gera um token de recurso que permite acesso somente leitura ou total a um determinado recurso e que pode ser qualquer recurso de usuário no banco de dados.

  • Os usuários são definidos no nível do banco de dados e as permissões são definidas para cada usuário.

  • Usuários e permissões se aplicam a todas as coleções no banco de dados.

Vamos dar uma olhada em um exemplo simples no qual aprenderemos como definir usuários e permissões para obter segurança granular no Banco de Dados de Documentos.

Começaremos com um novo DocumentClient e consultaremos o banco de dados 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");
   }
}

A seguir está a implementação de 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;
}

Step 1- Crie dois usuários, Alice e Tom como qualquer recurso que criarmos, construímos um objeto de definição com o Id desejado e chamamos o método de criação e, neste caso, estamos chamando CreateUserAsync com o SelfLink do banco de dados e o userDefinition. Recebemos o resultado de cuja propriedade de recurso obtemos o objeto de usuário recém-criado.

Agora, para ver esses dois novos usuários no banco de dados.

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); 
}

Step 2- Chame CreateUserQuery, contra o UsersLink do banco de dados para recuperar uma lista de todos os usuários. Em seguida, percorra-os e visualize suas propriedades.

Agora temos que criá-los primeiro. Então, digamos que desejamos permitir a Alice permissões de leitura / gravação para a coleção MyCollection, mas Tom só pode ler documentos na coleção.

await CreatePermission(client, alice, "Alice Collection Access", PermissionMode.All,
   collection);
	
await CreatePermission(client, tom, "Tom Collection Access", PermissionMode.Read,
   collection);

Step 3- Crie uma permissão em um recurso que seja a coleção MyCollection, portanto, precisamos obter um SelfLink para esse recurso.

Step 4 - Em seguida, crie um Permission.All nesta coleção para Alice e um Permission.Lead nesta coleção para Tom.

A seguir está a implementação de 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);
}

Como você já deve esperar, fazemos isso criando um objeto de definição para a nova permissão, que inclui um Id e um permissionMode, que é Permission.All ou Permission.Read, e o SelfLink do recurso que está sendo protegido pela permissão.

Step 5 - Chame CreatePermissionAsync e obtenha a permissão criada da propriedade do recurso no resultado.

Para visualizar a permissão criada, a seguir está a implementação de 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); 
}

Desta vez, é uma consulta de permissão no link de permissões do usuário e simplesmente listamos cada permissão retornada para o usuário.

Vamos deletar as permissões de Alice e Tom.

await DeletePermission(client, alice, "Alice Collection Access"); 
await DeletePermission(client, tom, "Tom Collection Access");

A seguir está a implementação de 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); 
}

Step 6 - Para excluir permissões, consulte por ID de permissão para obter o SelfLink e, em seguida, use o SelfLink para excluir a permissão.

A seguir, vamos excluir os próprios usuários. Vamos deletar ambos os usuários.

await DeleteUser(client, "Alice"); 
await DeleteUser(client, "Tom");

A seguir está a implementação de 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); 
}

Step 7 - Primeiro consulte para obter seu SelfLink e, em seguida, chame DeleteUserAsync para excluir seu objeto de usuário.

A seguir está a implementação da tarefa CreateDocumentClient na qual chamamos todas as tarefas acima.

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");
   }
}

Quando o código acima for compilado e executado, você receberá a seguinte saída.

**** 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