比较Windows文件(或文件夹)权限

本文关键字:文件夹 权限 Windows 文件 比较 | 更新日期: 2023-09-27 18:17:41

我偶尔会把一些网站从一个web服务器迁移到另一个web服务器。

将旧服务器上的所有文件复制到新服务器上后,我花了相当多的时间来(重新)熟悉哪些文件夹或文件需要由IIS可写。(顺便说一下,听起来很熟悉?:))

我写了一个WinForms应用程序,它允许我选择一个起始目录。应用程序应该(递归地)比较每个文件/目录的安全权限是否与其父目录的安全权限相等。

我想在旧服务器上使用这个应用程序来扫描具有不同权限的目录。

示例: C:'MySites'Uploads does not have the same permissions set as its parent directory.(此文件夹对IIS用户'IUSR'可写,而其父文件夹仅可读)

应用程序几乎完成了,因为我设法遍历了所有目录和文件。我只需要比较他们的权限!

你能帮帮我吗?以下是我需要你帮助的地方的摘录。

string results = "";
string parentFolderPath = "c:''someParentDir";
string childItemPath = "c:''someParentDir''SomeChildDir.ext";
DirectorySecurity parentFolderAccessControl = Directory.GetAccessControl(parentFolderPath);
DirectorySecurity childItemAccessControl = Directory.GetAccessControl(childItemPath);
if (!parentFolderAccessControl.Equals(childItemAccessControl)) // <-- D'oh here
{
    results += childItemPath + " does not have the same permissions set as its parent directory.'n";
}

if总是为真,因为DirectorySecurities永远不相等。(我理解这是为什么:引用不同的内存分配…等等。)但是比较DirectorySecurities的最好方法是什么呢?

比较Windows文件(或文件夹)权限

这实际上变得更加复杂,因为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;
}

不能使用Equals(),因为该方法继承自Object。您需要在DirectorySecurity类上找到一个标识属性。我认为GetSecurityDescriptorSddlForm()

应该完成你的工作。你可以在上面调用Equals()

编辑:很抱歉,这个方法需要一个参数来调用。尝试在DirectorySecurity上找到另一个更适合比较的属性。

我不熟悉。net安全框架和权限管理,但像这样的东西应该是你的方法。您可以在FileSystemAccessRule上执行!= resp: ==。FileSystemRights,因为该属性是一个enum(内部是int)。
ArrayList notIdenticalList = new ArrayList(); 
        DirectorySecurity parentFolderAccessControl = Directory.GetAccessControl(null);
        DirectorySecurity childItemAccessControl = Directory.GetAccessControl(null);
        foreach (FileSystemAccessRule parentRule in parentFolderAccessControl.GetAccessRules(true, true, typeof(NTAccount)))
        {
            foreach (FileSystemAccessRule childRule in childItemAccessControl.GetAccessRules(true, true, typeof(NTAccount)))
            {
                if (parentRule.FileSystemRights != childRule.FileSystemRights)
                {
                    // add to not identical-list
                    notIdenticalList.Add(fileToAdd...);
                    break;
                }
            }
        }