使用 .NET 管理 Azure Data Lake Storage Gen2 中的 ACLUse .NET to manage ACLs in Azure Data Lake Storage Gen2

本文介绍如何使用 .NET 来获取、设置和更新目录与文件的访问控制列表。This article shows you how to use .NET to get, set, and update the access control lists of directories and files.

ACL 继承已可用于在父目录下创建的新子项。ACL inheritance is already available for new child items that are created under a parent directory. 但是你也可以为父目录的现有子项以递归方式添加、更新和删除 ACL,而不必为每个子项单独进行这些更改。But you can also add, update, and remove ACLs recursively on the existing child items of a parent directory without having to make these changes individually for each child item.

包 (NuGet) | 示例 | 递归 ACL 示例 | API 参考 | 提供反馈Package (NuGet) | Samples | Recursive ACL Sample | API reference | Give Feedback

先决条件Prerequisites

  • Azure 订阅。An Azure subscription. 请参阅获取 Azure 试用版See Get Azure trial.

  • 一个已启用分层命名空间 (HNS) 的存储帐户。A storage account that has hierarchical namespace (HNS) enabled. 请按照此处的说明创建一个存储帐户。Follow these instructions to create one.

  • Azure CLI 版本 2.6.0 或更高版本。Azure CLI version 2.6.0 or higher.

  • 以下安全权限之一:One of the following security permissions:

    • 一个预配的 Azure Active Directory (AD) 安全主体,它在目标容器父资源组或订阅范围中分配有存储 Blob 数据所有者角色。A provisioned Azure Active Directory (AD) security principal that has been assigned the Storage Blob Data Owner role in the scope of the either the target container, parent resource group or subscription.

    • 计划将 ACL 设置应用到的目标容器或目录的拥有用户。Owning user of the target container or directory to which you plan to apply ACL settings. 为了以递归方式设置 ACL,这包括目标容器或目录中的所有子项。To set ACLs recursively, this includes all child items in the target container or directory.

    • 存储帐户密钥。Storage account key.

设置项目Set up your project

若要开始,请安装 Azure.Storage.Files.DataLake NuGet 包。To get started, install the Azure.Storage.Files.DataLake NuGet package.

  1. 打开一个命令窗口(例如 Windows PowerShell)。Open a command window (For example: Windows PowerShell).

  2. 从你的项目目录中,使用 dotnet add package 命令安装 Azure.Storage.Files.DataLake 预览版包。From your project directory, install the Azure.Storage.Files.DataLake preview package by using the dotnet add package command.

    dotnet add package Azure.Storage.Files.DataLake -v 12.6.0 -s https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json
    

    然后,将这些 using 语句添加到代码文件的顶部。Then, add these using statements to the top of your code file.

    using Azure;
    using Azure.Core;
    using Azure.Storage;
    using Azure.Storage.Files.DataLake;
    using Azure.Storage.Files.DataLake.Models;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    

连接到帐户Connect to the account

若要使用本文中的代码片段,需创建一个表示存储帐户的 DataLakeServiceClient 实例。To use the snippets in this article, you'll need to create a DataLakeServiceClient instance that represents the storage account.

使用 Azure Active Directory (AD) 进行连接Connect by using Azure Active Directory (AD)

备注

若要使用 Azure Active Directory (Azure AD) 来授予访问权限,请确保已为安全主体分配了存储 Blob 数据所有者角色If you're using Azure Active Directory (Azure AD) to authorize access, then make sure that your security principal has been assigned the Storage Blob Data Owner role. 若要详细了解如何应用 ACL 权限以及更改这些权限所带来的影响,请参阅 Azure Data Lake Storage Gen2 中的访问控制模型To learn more about how ACL permissions are applied and the effects of changing them, see Access control model in Azure Data Lake Storage Gen2.

可以使用适用于 .NET 的 Azure 标识客户端库,通过 Azure AD 对应用程序进行身份验证。You can use the Azure identity client library for .NET to authenticate your application with Azure AD.

安装包后,将此 using 语句添加到代码文件的顶部。After you install the package, add this using statement to the top of your code file.

using Azure.Identity;

获取客户端 ID、客户端机密和租户 ID。Get a client ID, a client secret, and a tenant ID. 若要执行此操作,请参阅从 Azure AD 获取用于对客户端应用程序的请求进行授权的令牌To do this, see Acquire a token from Azure AD for authorizing requests from a client application. 在该过程中,你必须为安全主体分配以下 Azure 基于角色的访问控制 (Azure RBAC) 角色之一。As part of that process, you'll have to assign one of the following Azure role-based access control (Azure RBAC) roles to your security principal.

角色Role ACL 设置功能ACL setting capability
存储 Blob 数据所有者Storage Blob Data Owner 帐户中的所有目录和文件。All directories and files in the account.
存储 Blob 数据参与者Storage Blob Data Contributor 仅限安全主体拥有的目录和文件。Only directories and files owned by the security principal.

此示例使用客户端 ID、客户端密码和租户 ID 创建 DataLakeServiceClient 实例This example creates a DataLakeServiceClient instance by using a client ID, a client secret, and a tenant ID.

public static void GetDataLakeServiceClient(ref DataLakeServiceClient dataLakeServiceClient,
    String accountName, String clientID, string clientSecret, string tenantID)
{

    TokenCredential credential = new ClientSecretCredential(
        tenantID, clientID, clientSecret, new TokenCredentialOptions());

    string dfsUri = "https://" + accountName + ".dfs.core.chinacloudapi.cn";

    dataLakeServiceClient = new DataLakeServiceClient(new Uri(dfsUri), credential);
}

备注

有关更多示例,请参阅适用于 .NET 的 Azure 标识客户端库文档。For more examples, see the Azure identity client library for .NET documentation..

使用帐户密钥进行连接Connect by using an account key

这是连接到帐户的最简单方法。This is the easiest way to connect to an account.

此示例使用帐户密钥创建 DataLakeServiceClient 实例This example creates a DataLakeServiceClient instance by using an account key.

public static void GetDataLakeServiceClient(ref DataLakeServiceClient dataLakeServiceClient,
    string accountName, string accountKey)
{
    StorageSharedKeyCredential sharedKeyCredential =
        new StorageSharedKeyCredential(accountName, accountKey);

    string dfsUri = "https://" + accountName + ".dfs.core.chinacloudapi.cn";

    dataLakeServiceClient = new DataLakeServiceClient
        (new Uri(dfsUri), sharedKeyCredential);
}

设置 ACLSet ACLs

设置 ACL 时,你将替换整个 ACL,包括其所有条目。When you set an ACL, you replace the entire ACL including all of it's entries. 如果要更改安全主体的权限级别,或将新的安全主体添加到 ACL 而不影响其他现有项,则应改为更新 ACL。If you want to change the permission level of a security principal or add a new security principal to the ACL without affecting other existing entries, you should update the ACL instead. 若要更新 ACL 而不是替换它,请参阅本文的更新 ACL 部分。To update an ACL instead of replace it, see the Update ACLs section of this article.

如果选择设置 ACL,则必须为责任用户添加一个条目,为责任组添加一个条目,为所有其他用户添加一个条目。If you choose to set the ACL, you must add an entry for the owning user, an entry for the owning group, and an entry for all other users. 若要详细了解责任用户、责任组和所有其他用户,请参阅用户和标识To learn more about the owning user, the owning group, and all other users, see Users and identities.

本部分介绍如何:This section shows you how to:

  • 设置目录的 ACLSet the ACL of a directory
  • 设置文件的 ACLSet the ACL of a file
  • 以递归方式设置 ACLSet ACLs recursively

设置目录的 ACLSet the ACL of a directory

可以通过调用 DataLakeDirectoryClient.GetAccessControlAsync 方法获取目录的访问控制列表 (ACL),并通过调用 DataLakeDirectoryClient.SetAccessControlList 方法来设置 ACL。Get the access control list (ACL) of a directory by calling the DataLakeDirectoryClient.GetAccessControlAsync method and set the ACL by calling the DataLakeDirectoryClient.SetAccessControlList method.

此示例获取并设置名为 my-directory 的目录的 ACL。This example gets and sets the ACL of a directory named my-directory. 字符串 user::rwx,group::r-x,other::rw- 为拥有用户提供读取、写入和执行权限,为拥有组授予读取和执行权限,并为所有其他用户提供读取和写入权限。The string user::rwx,group::r-x,other::rw- gives the owning user read, write, and execute permissions, gives the owning group only read and execute permissions, and gives all others read and write permission.

public async Task ManageDirectoryACLs(DataLakeFileSystemClient fileSystemClient)
{
    DataLakeDirectoryClient directoryClient =
      fileSystemClient.GetDirectoryClient("");

    PathAccessControl directoryAccessControl =
        await directoryClient.GetAccessControlAsync();

    foreach (var item in directoryAccessControl.AccessControlList)
    {
        Console.WriteLine(item.ToString());
    }

    IList<PathAccessControlItem> accessControlList
        = PathAccessControlExtensions.ParseAccessControlList
        ("user::rwx,group::r-x,other::rw-");

    directoryClient.SetAccessControlList(accessControlList);

}

还可以获取和设置容器根目录的 ACL。You can also get and set the ACL of the root directory of a container. 若要获取根目录,请将空字符串 ("") 传递到 DataLakeFileSystemClient.GetDirectoryClient 方法。To get the root directory, pass an empty string ("") into the DataLakeFileSystemClient.GetDirectoryClient method.

设置文件的 ACLSet the ACL of a file

可以通过调用 DataLakeFileClient.GetAccessControlAsync 方法获取文件的访问控制列表 (ACL),并通过调用 DataLakeFileClient.SetAccessControlList 方法来设置 ACL。Get the access control list (ACL) of a file by calling the DataLakeFileClient.GetAccessControlAsync method and set the ACL by calling the DataLakeFileClient.SetAccessControlList method.

此示例获取并设置名为 my-file.txt 的文件的 ACL。This example gets and sets the ACL of a file named my-file.txt. 字符串 user::rwx,group::r-x,other::rw- 为拥有用户提供读取、写入和执行权限,为拥有组授予读取和执行权限,并为所有其他用户提供读取和写入权限。The string user::rwx,group::r-x,other::rw- gives the owning user read, write, and execute permissions, gives the owning group only read and execute permissions, and gives all others read and write permission.

public async Task ManageFileACLs(DataLakeFileSystemClient fileSystemClient)
{
    DataLakeDirectoryClient directoryClient =
        fileSystemClient.GetDirectoryClient("my-directory");

    DataLakeFileClient fileClient =
        directoryClient.GetFileClient("hello.txt");

    PathAccessControl FileAccessControl =
        await fileClient.GetAccessControlAsync();

    foreach (var item in FileAccessControl.AccessControlList)
    {
        Console.WriteLine(item.ToString());
    }

    IList<PathAccessControlItem> accessControlList
        = PathAccessControlExtensions.ParseAccessControlList
        ("user::rwx,group::r-x,other::rw-");

    fileClient.SetAccessControlList(accessControlList);
}

以递归方式设置 ACLSet ACLs recursively

通过调用 DataLakeDirectoryClient.SetAccessControlRecursiveAsync 方法以递归方式设置 ACL。Set ACLs recursively by calling the DataLakeDirectoryClient.SetAccessControlRecursiveAsync method. 向此方法传递 PathAccessControlItem列表Pass this method a List of PathAccessControlItem. 每个 PathAccessControlItem 定义一个 ACL 条目。Each PathAccessControlItem defines an ACL entry.

如果要设置 默认 ACL 条目,请将 PathAccessControlItemPathAccessControlItem.DefaultScope 属性设置为 trueIf you want to set a default ACL entry, then you can set the PathAccessControlItem.DefaultScope property of the PathAccessControlItem to true.

此示例设置名为 my-parent-directory 的目录的 ACL。This example sets the ACL of a directory named my-parent-directory. 此方法接受一个名为 isDefaultScope 的布尔参数,该参数指定是否设置默认 ACL。This method accepts a boolean parameter named isDefaultScope that specifies whether to set the default ACL. 该参数用在 PathAccessControlItem 的构造函数中。That parameter is used in the constructor of the PathAccessControlItem. ACL 的条目为所有者用户提供读取、写入和执行权限,仅为负责人组授予读取和执行权限,不为所有其他用户提供任何访问权限。The entries of the ACL give the owning user read, write, and execute permissions, gives the owning group only read and execute permissions, and gives all others no access. 此示例中的最后一个 ACL 条目为对象 ID 为“xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx”的特定用户提供读取和执行权限。The last ACL entry in this example gives a specific user with the object ID ""xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" read and execute permissions.

public async Task SetACLRecursively(DataLakeServiceClient serviceClient, bool isDefaultScope)
{
    DataLakeDirectoryClient directoryClient =
        serviceClient.GetFileSystemClient("my-container").
            GetDirectoryClient("my-parent-directory");

    List<PathAccessControlItem> accessControlList =
        new List<PathAccessControlItem>()
    {
new PathAccessControlItem(AccessControlType.User,
    RolePermissions.Read |
    RolePermissions.Write |
    RolePermissions.Execute, isDefaultScope),

new PathAccessControlItem(AccessControlType.Group,
    RolePermissions.Read |
    RolePermissions.Execute, isDefaultScope),

new PathAccessControlItem(AccessControlType.Other,
    RolePermissions.None, isDefaultScope),

new PathAccessControlItem(AccessControlType.User,
    RolePermissions.Read |
    RolePermissions.Execute, isDefaultScope,
    entityId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"),
    };

    await directoryClient.SetAccessControlRecursiveAsync
        (accessControlList, null);
}

若要查看通过指定批大小以递归方式成批设置 ACL 的示例,请参阅 .NET 示例To see an example that sets ACLs recursively in batches by specifying a batch size, see the .NET sample.

更新 ACLUpdate ACLs

更新 ACL 时,你将修改 ACL 而非替换 ACL。When you update an ACL, you modify the ACL instead of replacing the ACL. 例如,你可以将一个新的安全主体添加到 ACL,而不影响 ACL 中列出的其他安全主体。For example, you can add a new security principal to the ACL without affecting other security principals listed in the ACL. 若要替换 ACL 而不是更新它,请参阅本文的 设置 ACL 部分。To replace the ACL instead of update it, see the Set ACLs section of this article.

本部分介绍如何:This section shows you how to:

  • 更新 ACLUpdate an ACL
  • 以递归方式更新 ACLUpdate ACLs recursively

更新 ACLUpdate an ACL

首先,通过调用 DataLakeDirectoryClient. GetAccessControlAsync 方法来获取目录的 ACL。First, get the ACL of a directory by calling the DataLakeDirectoryClient.GetAccessControlAsync method. 将 ACL 条目的列表复制到 PathAccessControl 对象的新 ListCopy the list of ACL entries to a new List of PathAccessControl objects. 然后找到要更新的条目,并在列表中替换该条目。Then locate the entry that you want to update and replace it in the list. 通过调用 DataLakeDirectoryClient.setAccessControlList 方法来设置 ACL。Set the ACL by calling the DataLakeDirectoryClient.SetAccessControlList method.

此示例通过为所有其他用户都替换该 ACL 条目来更新容器的根 ACL。This example updates the root ACL of a container by replacing the ACL entry for all other users.

public async Task UpdateDirectoryACLs(DataLakeFileSystemClient fileSystemClient)
{
    DataLakeDirectoryClient directoryClient =
      fileSystemClient.GetDirectoryClient("");

    PathAccessControl directoryAccessControl =
        await directoryClient.GetAccessControlAsync();

    List<PathAccessControlItem> accessControlListUpdate 
        = (List<PathAccessControlItem>)directoryAccessControl.AccessControlList;

    int index = -1;

    foreach (var item in accessControlListUpdate)
    {
        if (item.AccessControlType == AccessControlType.Other)
        {
            index = accessControlListUpdate.IndexOf(item);
            break;
        }
    }

    if (index > -1)
    {
        accessControlListUpdate[index] = new PathAccessControlItem(AccessControlType.Other,
        RolePermissions.Read |
        RolePermissions.Execute);

        directoryClient.SetAccessControlList(accessControlListUpdate);
    }

   }

以递归方式更新 ACLUpdate ACLs recursively

若要以递归方式更新 ACL,请创建包含要更新的 ACL 条目的新 ACL 对象,然后在更新 ACL 的操作中使用该对象。To update an ACL recursively, create a new ACL object with the ACL entry that you want to update, and then use that object in update ACL operation. 不要获取现有 ACL,只需要提供要更新的 ACL 条目。Do not get the existing ACL, just provide ACL entries to be updated.

通过调用 DataLakeDirectoryClient.UpdateAccessControlRecursiveAsync 方法以递归方式更新 ACL。Update an ACL recursively by calling the DataLakeDirectoryClient.UpdateAccessControlRecursiveAsync method. 向此方法传递 PathAccessControlItem列表Pass this method a List of PathAccessControlItem. 每个 PathAccessControlItem 定义一个 ACL 条目。Each PathAccessControlItem defines an ACL entry.

如果要更新 默认 ACL 条目,请将 PathAccessControlItemPathAccessControlItem.DefaultScope 属性设置为 trueIf you want to update a default ACL entry, then you can set the PathAccessControlItem.DefaultScope property of the PathAccessControlItem to true.

此示例以写入权限更新某个 ACL 条目。This example updates an ACL entry with write permission. 此方法接受一个名为 isDefaultScope 的布尔参数,该参数指定是否更新默认 ACL。This method accepts a boolean parameter named isDefaultScope that specifies whether to update the default ACL. 该参数用在 PathAccessControlItem 的构造函数中。That parameter is used in the constructor of the PathAccessControlItem.

public async Task UpdateACLsRecursively(DataLakeServiceClient serviceClient, bool isDefaultScope)
{
    DataLakeDirectoryClient directoryClient =
        serviceClient.GetFileSystemClient("my-container").
        GetDirectoryClient("my-parent-directory");

    List<PathAccessControlItem> accessControlListUpdate =
        new List<PathAccessControlItem>()
    {
new PathAccessControlItem(AccessControlType.User,
    RolePermissions.Read |
    RolePermissions.Write |
    RolePermissions.Execute, isDefaultScope,
    entityId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"),
    };

    await directoryClient.UpdateAccessControlRecursiveAsync
        (accessControlListUpdate, null);

}

若要查看通过指定批大小以递归方式成批更新 ACL 的示例,请参阅 .NET 示例To see an example that updates ACLs recursively in batches by specifying a batch size, see the .NET sample.

删除 ACL 条目Remove ACL entries

可以删除一个或多个 ACL 条目。You can remove one or more ACL entries. 本部分介绍如何:This section shows you how to:

  • 删除 ACL 条目Remove an ACL entry
  • 以递归方式删除 ACL 条目Remove ACL entries recursively

删除 ACL 条目Remove an ACL entry

首先,通过调用 DataLakeDirectoryClient. GetAccessControlAsync 方法来获取目录的 ACL。First, get the ACL of a directory by calling the DataLakeDirectoryClient.GetAccessControlAsync method. 将 ACL 条目的列表复制到 PathAccessControl 对象的新 ListCopy the list of ACL entries to a new List of PathAccessControl objects. 然后找到要删除的条目,并调用集合的 Remove 方法。Then locate the entry that you want to remove and call the Remove method of the collection. 通过调用 DataLakeDirectoryClient.SetAccessControlList 方法来设置已更新的 ACL。Set the updated ACL by calling the DataLakeDirectoryClient.SetAccessControlList method.

此示例通过为所有其他用户都替换该 ACL 条目来更新容器的根 ACL。This example updates the root ACL of a container by replacing the ACL entry for all other users.

public async Task RemoveDirectoryACLEntry
    (DataLakeFileSystemClient fileSystemClient)
{
    DataLakeDirectoryClient directoryClient =
      fileSystemClient.GetDirectoryClient("");

    PathAccessControl directoryAccessControl =
        await directoryClient.GetAccessControlAsync();

    List<PathAccessControlItem> accessControlListUpdate
        = (List<PathAccessControlItem>)directoryAccessControl.AccessControlList;

    PathAccessControlItem entryToRemove = null;

    foreach (var item in accessControlListUpdate)
    {
        if (item.EntityId == "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")
        {
            entryToRemove = item;
            break;
        }
    }

    if (entryToRemove != null)
    {
        accessControlListUpdate.Remove(entryToRemove);
        directoryClient.SetAccessControlList(accessControlListUpdate);
    }

}

以递归方式删除 ACL 条目Remove ACL entries recursively

若要以递归方式删除 ACL 条目,请为要删除的 ACL 条目创建新 ACL 对象,然后在删除 ACL 的操作中使用该对象。To remove ACL entries recursively, create a new ACL object for ACL entry to be removed, and then use that object in remove ACL operation. 不要获取现有 ACL,只需要提供要删除的 ACL 条目。Do not get the existing ACL, just provide the ACL entries to be removed.

通过调用 DataLakeDirectoryClient.RemoveAccessControlRecursiveAsync 方法删除 ACL 条目。Remove ACL entries by calling the DataLakeDirectoryClient.RemoveAccessControlRecursiveAsync method. 向此方法传递 PathAccessControlItem列表Pass this method a List of PathAccessControlItem. 每个 PathAccessControlItem 定义一个 ACL 条目。Each PathAccessControlItem defines an ACL entry.

如果要删除 默认 ACL 条目,请将 PathAccessControlItemPathAccessControlItem.DefaultScope 属性设置为 trueIf you want to remove a default ACL entry, then you can set the PathAccessControlItem.DefaultScope property of the PathAccessControlItem to true.

此示例从名为 my-parent-directory 的目录的 ACL 中删除 ACL 条目。This example removes an ACL entry from the ACL of the directory named my-parent-directory. 此方法接受一个名为 isDefaultScope 的布尔参数,该参数指定是否删除默认 ACL 中的条目。This method accepts a boolean parameter named isDefaultScope that specifies whether to remove the entry from the default ACL. 该参数用在 PathAccessControlItem 的构造函数中。That parameter is used in the constructor of the PathAccessControlItem.

public async Task RemoveACLsRecursively(DataLakeServiceClient serviceClient, bool isDefaultScope)
{
    DataLakeDirectoryClient directoryClient =
        serviceClient.GetFileSystemClient("my-container").
            GetDirectoryClient("my-parent-directory");

    List<RemovePathAccessControlItem> accessControlListForRemoval =
        new List<RemovePathAccessControlItem>()
        {
    new RemovePathAccessControlItem(AccessControlType.User, isDefaultScope,
    entityId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"),
        };

    await directoryClient.RemoveAccessControlRecursiveAsync
        (accessControlListForRemoval, null);

}

若要查看通过指定批大小以递归方式成批删除 ACL 的示例,请参阅 .NET 示例To see an example that removes ACLs recursively in batches by specifying a batch size, see the .NET sample.

从故障中恢复Recover from failures

以递归方式修改 ACL 时,可能会遇到运行时错误或权限错误。You might encounter runtime or permission errors when modifying ACLs recursively. 对于运行时错误,请从头开始重启此过程。For runtime errors, restart the process from the beginning. 如果安全主体没有足够的权限修改要修改的目录层次结构中的目录或文件的 ACL,则会出现权限错误。Permission errors can occur if the security principal doesn't have sufficient permission to modify the ACL of a directory or file that is in the directory hierarchy being modified. 请解决权限问题,然后选择通过使用继续标记从故障点继续执行此过程,或者从头重启此过程。Address the permission issue, and then choose to either resume the process from the point of failure by using a continuation token, or restart the process from beginning. 如果希望从头开始重启,则无需使用继续标记。You don't have to use the continuation token if you prefer to restart from the beginning. 你可以重新应用 ACL 条目,而不会产生任何负面影响。You can reapply ACL entries without any negative impact.

此示例在失败时返回一个继续标记。This example returns a continuation token in the event of a failure. 应用程序可以在错误得到解决后再次调用此示例方法,并传入继续标记。The application can call this example method again after the error has been addressed, and pass in the continuation token. 如果是第一次调用此示例方法,则应用程序可以为继续标记参数传入 null 值。If this example method is called for the first time, the application can pass in a value of null for the continuation token parameter.

public async Task<string> ResumeAsync(DataLakeServiceClient serviceClient,
    DataLakeDirectoryClient directoryClient,
    List<PathAccessControlItem> accessControlList,
    string continuationToken)
{
    try
    {
        var accessControlChangeResult =
            await directoryClient.SetAccessControlRecursiveAsync(
                accessControlList, continuationToken: continuationToken, null);

        if (accessControlChangeResult.Value.Counters.FailedChangesCount > 0)
        {
            continuationToken =
                accessControlChangeResult.Value.ContinuationToken;
        }

        return continuationToken;
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
        return continuationToken;
    }

}

若要查看通过指定批大小以递归方式成批设置 ACL 的示例,请参阅 .NET 示例To see an example that sets ACLs recursively in batches by specifying a batch size, see the .NET sample.

如果你希望过程继续完成而不被权限错误中断,则可以指定它。If you want the process to complete uninterrupted by permission errors, you can specify that.

若要确保过程无中断地完成,请传入 AccessControlChangedOptions 对象,并将该对象的 ContinueOnFailure 属性设置为 trueTo ensure that the process completes uninterrupted, pass in an AccessControlChangedOptions object and set the ContinueOnFailure property of that object to true.

此示例以递归方式设置 ACL 条目。This example sets ACL entries recursively. 如果此代码遇到权限错误,它会记录该故障并继续执行。If this code encounters a permission error, it records that failure and continues execution. 此示例将故障数输出到控制台。This example prints the number of failures to the console.

public async Task ContinueOnFailureAsync(DataLakeServiceClient serviceClient,
    DataLakeDirectoryClient directoryClient,
    List<PathAccessControlItem> accessControlList)
{
    var accessControlChangeResult =
        await directoryClient.SetAccessControlRecursiveAsync(
            accessControlList, null, new AccessControlChangeOptions()
            { ContinueOnFailure = true });

    var counters = accessControlChangeResult.Value.Counters;

    Console.WriteLine("Number of directories changed: " +
        counters.ChangedDirectoriesCount.ToString());

    Console.WriteLine("Number of files changed: " +
        counters.ChangedFilesCount.ToString());

    Console.WriteLine("Number of failures: " +
        counters.FailedChangesCount.ToString());
}

若要查看通过指定批大小以递归方式成批设置 ACL 的示例,请参阅 .NET 示例To see an example that sets ACLs recursively in batches by specifying a batch size, see the .NET sample.

最佳实践Best practices

本部分提供了有关以递归方式设置 ACL 的一些最佳做法指南。This section provides you some best practice guidelines for setting ACLs recursively.

处理运行时错误Handling runtime errors

发生运行时错误可能有许多原因(例如:中断或客户端连接问题)。A runtime error can occur for many reasons (For example: an outage or a client connectivity issue). 如果遇到运行时错误,请重启递归 ACL 过程。If you encounter a runtime error, restart the recursive ACL process. 可以将 ACL 重新应用于项,而不会造成负面影响。ACLs can be reapplied to items without causing a negative impact.

处理权限错误 (403)Handling permission errors (403)

如果在运行递归 ACL 过程时遇到访问控制异常,则表明 AD 安全主体可能没有足够的权限将 ACL 应用于目录层次结构中的一个或多个子项。If you encounter an access control exception while running a recursive ACL process, your AD security principal might not have sufficient permission to apply an ACL to one or more of the child items in the directory hierarchy. 发生权限错误时,此过程会停止,系统会提供一个继续标记。When a permission error occurs, the process stops and a continuation token is provided. 请修复权限问题,然后使用继续标记来处理剩余的数据集。Fix the permission issue, and then use the continuation token to process the remaining dataset. 已成功处理的目录和文件不需要再次处理。The directories and files that have already been successfully processed won't have to be processed again. 你还可以选择重启递归 ACL 过程。You can also choose to restart the recursive ACL process. 可以将 ACL 重新应用于项,而不会造成负面影响。ACLs can be reapplied to items without causing a negative impact.

凭据Credentials

建议你预配一个在目标存储帐户或容器范围中分配有存储 Blob 数据所有者角色的 Azure AD 安全主体。We recommend that you provision an Azure AD security principal that has been assigned the Storage Blob Data Owner role in the scope of the target storage account or container.

性能Performance

为了减少延迟,建议你在与存储帐户位于同一区域中的 Azure 虚拟机 (VM) 中运行递归 ACL 过程。To reduce latency, we recommend that you run the recursive ACL process in an Azure Virtual Machine (VM) that is located in the same region as your storage account.

ACL 限制ACL limits

可应用于目录或文件的 ACL 的最大数目为 32 个访问 ACL 和 32 个默认 ACL。The maximum number of ACLs that you can apply to a directory or file is 32 access ACLs and 32 default ACLs. 有关详细信息,请参阅 Azure Data Lake Storage Gen2 中的访问控制For more information, see Access control in Azure Data Lake Storage Gen2.

另请参阅See also