为包含许多文件的文件夹设置 ACE 慢

本文关键字:设置 ACE 文件夹 包含许 文件 | 更新日期: 2023-09-27 18:31:27

我们创建了一个应用程序,该应用程序提供了在某个Active Directory组的Windows文件夹上设置递归"拒绝"的功能。基本上与进入Windows资源管理器中的属性对话框并单击安全性并在拒绝权限下添加AD组相同。我们使用以下代码:

public void DenyAccessInherited(string DomainAndSamAccountName)
    {
        SetPermissionAndInherit(this.FolderPath, 
            NTFSPermission.PropagationFlags.CONTAINER_AND_OBJECT_INHERIT_ACE,
            NTFSPermission.NTFSPermission_FULL_CONTROL, NTFSPermission.ACETypes.ADS_ACETYPE_ACCESS_DENIED,
            DomainAndSamAccountName);
    }
public static void SetPermissionAndInherit(string FolderPath, PropagationFlags Inheritance, int Permission, ACETypes ACETypeAccessAllowedDenied, string DomainAndUsername)
    {
        AccessControlList dacl = new AccessControlList();
        SecurityDescriptor sd = new SecurityDescriptor();
        AccessControlEntry newAce = new AccessControlEntry();
        ADsSecurityUtility sdUtil = new ADsSecurityUtility();
        OnProgress(DomainAndUsername, FolderPath);
        sd = sdUtil.GetSecurityDescriptor(FolderPath, ADS_PATH_FILE, ADS_SD_FORMAT_IID);
        dacl = sd.DiscretionaryAcl;
        RemoveTrusteeFromDACL(dacl, DomainAndUsername);
        newAce.Trustee = DomainAndUsername;
        newAce.AccessMask = Permission;
        newAce.AceFlags = (int)Inheritance;
        newAce.AceType = (int)ACETypeAccessAllowedDenied;
        dacl.AddAce(newAce);
        sdUtil.SetSecurityDescriptor(FolderPath, ADS_PATH_FILE, sd, ADS_SD_FORMAT_IID);
        foreach (string File in Directory.GetFiles(FolderPath))
        {
            SetACE(File, DomainAndUsername, Permission, PropagationFlags.INHERITED_ACE, ACETypeAccessAllowedDenied);
        }
        foreach (string SubFolderPath in Directory.GetDirectories(FolderPath))
        {
            SetInheritedPermission(SubFolderPath, DomainAndUsername, Permission, ACETypeAccessAllowedDenied);
        }
    }
private static void SetInheritedPermission(string FolderPath, string DomainAndUsername, int PermissionFlags, ACETypes AccessFlags)
    {
        AccessControlList dacl = new AccessControlList();
        SecurityDescriptor sd = new SecurityDescriptor();
        AccessControlEntry newAce = new AccessControlEntry();
        ADsSecurityUtility sdUtil = new ADsSecurityUtility();
        SetACE(FolderPath, DomainAndUsername, PermissionFlags, (PropagationFlags)(PropagationFlags.CONTAINER_AND_OBJECT_INHERIT_ACE | PropagationFlags.INHERITED_ACE), AccessFlags);
        foreach (string File in Directory.GetFiles(FolderPath))
        {
            SetACE(File, DomainAndUsername, PermissionFlags, PropagationFlags.INHERITED_ACE, AccessFlags);
        }
        foreach (string SubFolderPath in Directory.GetDirectories(FolderPath))
        {
            SetInheritedPermission(SubFolderPath, DomainAndUsername, PermissionFlags, AccessFlags);
        }
    }

private static void SetACE(string FileOrFolder, string DomainAndUsername, int PermissionFlags, PropagationFlags InheritanceFlags, ACETypes AccessFlags)
    {
        AccessControlList dacl = new AccessControlList();
        SecurityDescriptor sd = new SecurityDescriptor();
        AccessControlEntry newAce = new AccessControlEntry();
        ADsSecurityUtility sdUtil = new ADsSecurityUtility(); sd = sdUtil.GetSecurityDescriptor(FileOrFolder, ADS_PATH_FILE, ADS_SD_FORMAT_IID);
        sd.Control = sd.Control;
        OnProgress(DomainAndUsername, FileOrFolder);
        dacl = sd.DiscretionaryAcl;
        RemoveTrusteeFromDACL(dacl, DomainAndUsername);
        newAce.Trustee = DomainAndUsername;
        newAce.AccessMask = PermissionFlags;
        newAce.AceFlags = (int)InheritanceFlags;
        newAce.AceType = (int)AccessFlags;
        dacl.AddAce(newAce);
        sdUtil.SetSecurityDescriptor(FileOrFolder, ADS_PATH_FILE, sd, ADS_SD_FORMAT_IID);
    }

现在我们遇到了一个大文件夹,里面有很多html文档,大约有12000个文件,上面的方法很慢。处理文件安全性大约需要 7 分钟。但是,当通过Windows资源管理器/安全性管理安全性时,只需要大约20秒,因此必须有某种方法可以在C#中对其进行优化。

编辑:当我省略递归并且只在顶部文件夹上设置安全描述符时,它下面的文件都没有拒绝 AD 组,只有顶部文件夹。

为包含许多文件的文件夹设置 ACE 慢

我解决了。我完全转储了上面的代码,走了另一条路:

public override void DenyAccessInherited(string FolderPath,string DomainAndSamAccountName)
    {
        using (Impersonator imp = new Impersonator(this.connection.GetSamAccountName(), this.connection.GetDomain(), this.connection.Password))
        {
            FileSystemAccessRule rule = new FileSystemAccessRule(DomainAndSamAccountName, FileSystemRights.FullControl, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, System.Security.AccessControl.PropagationFlags.InheritOnly, AccessControlType.Deny);
            DirectoryInfo di = new DirectoryInfo(FolderPath);
            DirectorySecurity security = di.GetAccessControl(AccessControlSections.All);
            bool modified;
            security.ModifyAccessRule(AccessControlModification.Add, rule, out modified);
            if (modified)
                di.SetAccessControl(security);
        }
    }

这是非常苗条和非常快的。

嵌套文件夹和文件应继承父级的安全设置,因此您无需为所有人递归设置它。尝试仅为根文件夹设置它。