【问题标题】:Using System.Security.AccessControl to remove an ACE from a folder ACL is very slow if the target folder size is very large如果目标文件夹非常大,则使用 System.Security.AccessControl 从文件夹 ACL 中删除 ACE 会非常慢
【发布时间】:2011-07-20 19:08:09
【问题描述】:

我需要从共享的特定子文件夹上的 ACL 中删除某些帐户(例如“所有人”受托人或某个授予所有人访问文件夹的全局组)。我得到一个 DirectorySecurity 对象,获取并遍历 AuthorizationRuleCollection,从 ACL 中删除有问题的 AccessRule,然后调用 SetAccessControl 来应用更改。如果目标文件夹很小,一切正常,但如果它有很多子文件夹和文件,则应用更改可能需要很长时间(比手动执行要长得多)。我只想处理目标文件夹上的 ACL。有没有办法使用 .net DirectorySecurity 类来做到这一点?还是我必须求助于 Win32 API 或其他解决方案?谢谢。

这是一个sn-p的代码。对 dirInfo.SetAccessControl(dirSec) 的调用是文件夹很大时挂起的地方。

DirectoryInfo dirInfo = new DirectoryInfo(path);
DirectorySecurity dirSec = dirInfo.GetAccessControl();
AuthorizationRuleCollection acl = dirSec.GetAccessRules(true, true,     
                                  typeof(System.Security.Principal.NTAccount));
foreach (FileSystemAccessRule ace in acl)
{
    if (groupsToRemove.Contains(ace.IdentityReference.Value))
    {
        dirSec.RemoveAccessRuleSpecific(ace);
        dirInfo.SetAccessControl(dirSec);
    }
}

【问题讨论】:

    标签: c# .net directory-security


    【解决方案1】:
    DirectoryInfo dirInfo = new DirectoryInfo(path);
    DirectorySecurity dirSec = dirInfo.GetAccessControl();
    AuthorizationRuleCollection acl = dirSec.GetAccessRules(true, true,     
                                      typeof(System.Security.Principal.NTAccount));
    foreach (FileSystemAccessRule ace in acl)
    {
        if (groupsToRemove.Contains(ace.IdentityReference.Value))
        {
            dirSec.RemoveAccessRuleSpecific(ace);
            dirInfo.SetAccessControl(dirSec);
        }
    }
    

    在您的代码中,您在循环的每次交互中都将更新应用到 ACL,这会变得非常昂贵。您是否尝试将 dirInfo.SetAccessControl(dirSec); 移到 foreach 之外?这应该在您的 DirectoryInfo 对象上调用一次 SetAccessControl 方法,一次应用所有更改,如下所示:

    foreach (FileSystemAccessRule ace in acl)
    {
        if (groupsToRemove.Contains(ace.IdentityReference.Value))
        {
            dirSec.RemoveAccessRuleSpecific(ace);        
        }
    }
    dirInfo.SetAccessControl(dirSec);
    

    【讨论】:

    • 自从我第一次发布这个已经很长时间了,我不再从事那个项目了,很抱歉直到现在我才看到你的答案。如果我没记错的话,我并没有删除很多组(我相信只有 2 个),所以我认为应用更新不会导致极度延迟。但是,我确实认为您的代码是更好的方法,特别是如果有很多组要删除。谢谢!
    【解决方案2】:

    您必须设置 SE_DACL_PROTECTED 标志以“防止在父容器的 DACL 上设置的 ACE,以及​​目录层次结构中父容器上方的任何对象应用于对象 DACL。”这可能会加快您的操作,因为它不必将其应用于所有子对象。同样来自 MSDN,

    请注意,必须存在 SE_DACL_PRESENT 标志才能设置 SE_DACL_PROTECTED 和 SE_SACL_PRESENT 必须存在才能设置 SE_SACL_PROTECTED。

    然后您必须使用 IADsSecurityDescriptor.Control 属性来控制 DACL 和 SACL 是否由对象从其父容器继承。

    有关IADsSecurityDescriptor 接口的更多信息,请访问 MSDN。

    【讨论】:

    • 感谢 0A0D,但我认为这不是我特定问题的答案。我正在使用 C#,因此在阅读了您的答案后,我添加了一些代码来检查 DirectorySecurity.AreAccessRulesProtected,并检查了其中一个存在问题的文件夹。它已经受到保护,因此它不是从父文件夹继承的。 (如果您通过 Windows GUI 查看高级安全设置,则未选中“允许从父级继承的权限传播到此对象和所有子对象...”复选框。)我真的认为我的问题是由于大文件夹大小。还有其他想法吗?
    • 你的意思是一个包含大量文件的文件夹?
    • 是的,我正在测试的文件夹共有 100 个子文件夹和 3672 个文件,大小为 1.87GB。但是该文件夹受到保护,不会被继承,如果我要手动删除 ACE,它只需要一秒钟。
    • 我将代码 sn-p 添加到我原来的问题中,所以我可以更好地格式化它。谢谢。
    • 是的。路径格式为\\server\drive$\folder\subfolder。感谢您在这方面的持续帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-23
    相关资源
    最近更新 更多