Учебники

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 — Создайте двух пользователей, Алису и Том, как любой ресурс, который мы создаем, мы создаем объект определения с желаемым Id и вызываем метод create, и в этом случае мы вызываем CreateUserAsync с базой данных SelfLink и userDefinition. Мы получаем результат, из свойства ресурса которого получаем вновь созданный пользовательский объект.

Теперь, чтобы увидеть этих двух новых пользователей в базе данных.

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. Вызовите CreateUserQuery для базы данных UsersLink, чтобы получить список всех пользователей. Затем просмотрите их и просмотрите их свойства.

Теперь мы должны сначала создать их. Допустим, мы хотели предоставить Алисе разрешения на чтение / запись для коллекции MyCollection, но Том может только читать документы в коллекции.

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

Шаг 3 — Создайте разрешение для ресурса, который является коллекцией MyCollection, поэтому нам нужно получить этот ресурс SelfLink.

Шаг 4 — Затем создайте Permission.All для этой коллекции для Алисы и Permission.Read для этой коллекции для Tom.

Ниже приводится реализация для 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 и allowMode, который является либо 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); 
}

На этот раз это запрос разрешения на ссылку разрешения пользователя, и мы просто перечисляем каждое разрешение, возвращаемое пользователю.

Давайте удалим разрешения Алисы и Тома.

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. Чтобы удалить разрешения, выполните запрос по идентификатору разрешения, чтобы получить 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");
   }
}

Когда приведенный выше код скомпилирован и выполнен, вы получите следующий вывод.