问题
we have created an application which provides the ability to set a recursive "Deny" on a windows folder for a certain Active Directory group. Basically the same as going into the properties dialog in windows explorer and clicking on security and the adding an AD group with the permission of Deny. We are using this code:
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);
}
Now we have encountered a large folder with lots of html documents, about 12000 files, and the method above is very slow. It takes about 7 minutes to process the file security. However, when managing security through windows explorer/security it only takes about 20 seconds so there must be some way to optimize this in C#.
Edit: When I leave out the recursion and only set the SecurityDescriptor on the top folder, none of the files below it have the deny for the AD group, only the top folder.
回答1:
I solved it. I completely dumped the above code and went another way:
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);
}
}
This is very slim and very fast.
回答2:
Nested folders and files should inherit parent's security settings so you don't need to set it recursively for all. Try to set it only for root folder.
来源:https://stackoverflow.com/questions/10174585/setting-ace-slow-for-folder-with-many-files