Использование System.Security.AccessControl для удаления ACE из папки ACL очень медленный, если размер целевой папки очень большой - PullRequest
2 голосов
/ 20 июля 2011

Мне нужно удалить определенные учетные записи (например, опекуна «Все» или какую-либо глобальную группу, которая предоставляет всем доступ к папке) из ACL-списка в определенной подпапке общего ресурса. Я получаю объект DirectorySecurity, получаю и перебираю AuthorizationRuleCollection, удаляю рассматриваемый AccessRule из ACL, а затем вызываю SetAccessControl для применения изменений. Все работает нормально, если целевая папка небольшая, но если в ней много дочерних папок и файлов, для внесения изменений может потребоваться вечность (гораздо дольше, чем просто сделать это вручную). Я только хочу иметь дело с ACL на целевой папке. Есть ли способ сделать это с помощью классов .net DirectorySecurity? Или мне нужно прибегнуть к Win32 API или какому-то другому решению? Спасибо.

Вот фрагмент кода. При вызове 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);
    }
}

Ответы [ 2 ]

2 голосов
/ 11 марта 2012
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? Это должно вызвать метод SetAccessControl для вашего объекта DirectoryInfo один раз, применяя все изменения за один проход, например:

foreach (FileSystemAccessRule ace in acl)
{
    if (groupsToRemove.Contains(ace.IdentityReference.Value))
    {
        dirSec.RemoveAccessRuleSpecific(ace);        
    }
}
dirInfo.SetAccessControl(dirSec);
1 голос
/ 20 июля 2011

Необходимо установить флаг SE_DACL_PROTECTED , чтобы «предотвратить применение ACE, заданных в DACL родительского контейнера, и любых объектов над родительским контейнером в иерархии каталогов, применяемых к объекту DACL». «. Это, скорее всего, ускорит вашу работу, потому что не придется применять все дочерние объекты. Также из MSDN,

Имейте в виду, что флаг SE_DACL_PRESENT должен присутствовать для установки SE_DACL_PROTECTED и SE_SACL_PRESENT должны присутствовать для установки SE_SACL_PROTECTED.

Затем необходимо использовать свойство IADsSecurityDescriptor.Control , чтобы управлять наследованием DACL и SACL объектом от его родительского контейнера.

Дополнительная информация доступна в MSDN для интерфейса IADsSecurityDescriptor .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...