在我解决这个问题时,这实际上变得更加复杂,因为 Windows 权限可以:
- 分为允许和拒绝
- 分散在多个条目上(每个用户每个允许/拒绝多个条目)
最终,这就是我做出来的:
private bool compareAccessControls(
DirectorySecurity parentAccessControl,
DirectorySecurity childAccessControl,
out Dictionary<IdentityReference, FileSystemRights> accessAllowRulesGainedByChild,
out Dictionary<IdentityReference, FileSystemRights> accessDenyRulesGainedByChild,
out Dictionary<IdentityReference, FileSystemRights> accessAllowRulesGainedByParent,
out Dictionary<IdentityReference, FileSystemRights> accessDenyRulesGainedByParent
)
{
// combine parent access rules
Dictionary<IdentityReference, FileSystemRights> combinedParentAccessAllowRules = new Dictionary<IdentityReference, FileSystemRights>();
Dictionary<IdentityReference, FileSystemRights> combinedParentAccessDenyRules = new Dictionary<IdentityReference, FileSystemRights>();
foreach (FileSystemAccessRule parentAccessRule in parentAccessControl.GetAccessRules(true, true, typeof(NTAccount)))
{
if (parentAccessRule.AccessControlType == AccessControlType.Allow)
if (combinedParentAccessAllowRules.ContainsKey(parentAccessRule.IdentityReference))
combinedParentAccessAllowRules[parentAccessRule.IdentityReference] = combinedParentAccessAllowRules[parentAccessRule.IdentityReference] | parentAccessRule.FileSystemRights;
else
combinedParentAccessAllowRules.Add(parentAccessRule.IdentityReference, parentAccessRule.FileSystemRights);
else
if (combinedParentAccessDenyRules.ContainsKey(parentAccessRule.IdentityReference))
combinedParentAccessDenyRules[parentAccessRule.IdentityReference] = combinedParentAccessDenyRules[parentAccessRule.IdentityReference] | parentAccessRule.FileSystemRights;
else
combinedParentAccessDenyRules.Add(parentAccessRule.IdentityReference, parentAccessRule.FileSystemRights);
}
// combine child access rules
Dictionary<IdentityReference, FileSystemRights> combinedChildAccessAllowRules = new Dictionary<IdentityReference, FileSystemRights>();
Dictionary<IdentityReference, FileSystemRights> combinedChildAccessDenyRules = new Dictionary<IdentityReference, FileSystemRights>();
foreach (FileSystemAccessRule childAccessRule in childAccessControl.GetAccessRules(true, true, typeof(NTAccount)))
{
if (childAccessRule.AccessControlType == AccessControlType.Allow)
if (combinedChildAccessAllowRules.ContainsKey(childAccessRule.IdentityReference))
combinedChildAccessAllowRules[childAccessRule.IdentityReference] = combinedChildAccessAllowRules[childAccessRule.IdentityReference] | childAccessRule.FileSystemRights;
else
combinedChildAccessAllowRules.Add(childAccessRule.IdentityReference, childAccessRule.FileSystemRights);
else
if (combinedChildAccessDenyRules.ContainsKey(childAccessRule.IdentityReference))
combinedChildAccessDenyRules[childAccessRule.IdentityReference] = combinedChildAccessDenyRules[childAccessRule.IdentityReference] | childAccessRule.FileSystemRights;
else
combinedChildAccessDenyRules.Add(childAccessRule.IdentityReference, childAccessRule.FileSystemRights);
}
// compare combined rules
accessAllowRulesGainedByChild = new Dictionary<IdentityReference, FileSystemRights>();
foreach (KeyValuePair<IdentityReference, FileSystemRights> combinedChildAccessAllowRule in combinedChildAccessAllowRules)
{
if (combinedParentAccessAllowRules.ContainsKey(combinedChildAccessAllowRule.Key))
{
FileSystemRights accessAllowRuleGainedByChild = combinedChildAccessAllowRule.Value & ~combinedParentAccessAllowRules[combinedChildAccessAllowRule.Key];
if (accessAllowRuleGainedByChild != default(FileSystemRights))
accessAllowRulesGainedByChild.Add(combinedChildAccessAllowRule.Key, accessAllowRuleGainedByChild);
}
else
{
accessAllowRulesGainedByChild.Add(combinedChildAccessAllowRule.Key, combinedChildAccessAllowRule.Value);
}
}
accessDenyRulesGainedByChild = new Dictionary<IdentityReference, FileSystemRights>();
foreach (KeyValuePair<IdentityReference, FileSystemRights> combinedChildAccessDenyRule in combinedChildAccessDenyRules)
{
if (combinedParentAccessDenyRules.ContainsKey(combinedChildAccessDenyRule.Key))
{
FileSystemRights accessDenyRuleGainedByChild = combinedChildAccessDenyRule.Value & ~combinedParentAccessDenyRules[combinedChildAccessDenyRule.Key];
if (accessDenyRuleGainedByChild != default(FileSystemRights))
accessDenyRulesGainedByChild.Add(combinedChildAccessDenyRule.Key, accessDenyRuleGainedByChild);
}
else
{
accessDenyRulesGainedByChild.Add(combinedChildAccessDenyRule.Key, combinedChildAccessDenyRule.Value);
}
}
accessAllowRulesGainedByParent = new Dictionary<IdentityReference, FileSystemRights>();
foreach (KeyValuePair<IdentityReference, FileSystemRights> combinedParentAccessAllowRule in combinedParentAccessAllowRules)
{
if (combinedChildAccessAllowRules.ContainsKey(combinedParentAccessAllowRule.Key))
{
FileSystemRights accessAllowRuleGainedByParent = combinedParentAccessAllowRule.Value & ~combinedChildAccessAllowRules[combinedParentAccessAllowRule.Key];
if (accessAllowRuleGainedByParent != default(FileSystemRights))
accessAllowRulesGainedByParent.Add(combinedParentAccessAllowRule.Key, accessAllowRuleGainedByParent);
}
else
{
accessAllowRulesGainedByParent.Add(combinedParentAccessAllowRule.Key, combinedParentAccessAllowRule.Value);
}
}
accessDenyRulesGainedByParent = new Dictionary<IdentityReference, FileSystemRights>();
foreach (KeyValuePair<IdentityReference, FileSystemRights> combinedParentAccessDenyRule in combinedParentAccessDenyRules)
{
if (combinedChildAccessDenyRules.ContainsKey(combinedParentAccessDenyRule.Key))
{
FileSystemRights accessDenyRuleGainedByParent = combinedParentAccessDenyRule.Value & ~combinedChildAccessDenyRules[combinedParentAccessDenyRule.Key];
if (accessDenyRuleGainedByParent != default(FileSystemRights))
accessDenyRulesGainedByParent.Add(combinedParentAccessDenyRule.Key, accessDenyRuleGainedByParent);
}
else
{
accessDenyRulesGainedByParent.Add(combinedParentAccessDenyRule.Key, combinedParentAccessDenyRule.Value);
}
}
if (accessAllowRulesGainedByChild.Count > 0 || accessDenyRulesGainedByChild.Count > 0 || accessAllowRulesGainedByParent.Count > 0 || accessDenyRulesGainedByParent.Count > 0)
return false;
else
return true;
}