【问题标题】:How to prevent file deletion by ANY user如何防止任何用户删除文件
【发布时间】:2020-07-30 09:51:39
【问题描述】:

问题:需要防止删除单个 Windows 文件,至少在没有管理员权限的情况下。文件必须由“所有人”读取。 文件所在的 Windows 目录必须是“所有人”可写和可读的。

调试:下面的示例代码是我尝试在示例文件上设置“拒绝删除”访问控制规则(字符串“urlFilePath”包含执行此代码时实际文件的完整路径)。代码运行没有错误,但文件仍被所有人(和其他帐户)标记为可删除。

详情: 我有一个 C# 服务,可以将文件从即将退役的 FileNet WORM 存储系统迁移到 Windows 文件系统存储。

这些文件需要可供许多用户(实际上是“所有人”)访问,但必须保留以防删除 - 无论是意外还是故意。 文件所在的文件夹必须是可写的(必须允许某些用户添加以后的文件),所以我不能将文件夹设为只读。

我以为我可以添加 ACL 规则来“拒绝”删除,但以下代码不起作用。 是我犯了一个简单的错误还是我遗漏了一些技巧?

    string urlFilePath = @"\\server\directory\anotherdir\myfile.pdf";
    List<string> fileAccounts = new List<string>();
    FileInfo fi = new FileInfo(urlFilePath);
    FileSecurity fsec = fi.GetAccessControl();
    AuthorizationRuleCollection acl = fsec.GetAccessRules(includeExplicit: true, includeInherited: true, targetType: typeof(System.Security.Principal.NTAccount));
    foreach (FileSystemAccessRule acr in acl)
    {
        if (!fileAccounts.Contains(acr.IdentityReference.Value))
            fileAccounts.Add(acr.IdentityReference.Value);
    }

    //  populate standard accounts
    foreach (string s in new string[] { "GUEST", "USERS", "DOMAIN USERS", "NETWORK", "AUTHENTICATED USERS"})
    {
        if (!fileAccounts.Contains(s))
            fileAccounts.Add(s);
    }
    FileSecurity fileSecurity = File.GetAccessControl(urlFilePath);
    int numAccounts = 0;
    foreach (string account in fileAccounts)
    {
        fileSecurity.RemoveAccessRule(new FileSystemAccessRule(account, FileSystemRights.Delete, AccessControlType.Allow));
        fileSecurity.AddAccessRule(new FileSystemAccessRule(account, FileSystemRights.Delete, AccessControlType.Deny));
        numAccounts++;
    }

在上面,我遵循(我认为)添加/删除 ACL 规则的 MS 示例。我没有收到任何错误、警告或异常,但这些文件仍然可以被所有人完全删除。我明确添加了帐户列表,认为可能已经与文件关联的帐户还不够。当它运行时,它报告删除/添加循环针对 9 个帐户运行 - 我添加的 5 个,加上已关联的 4 个,因此删除规则/添加规则循环正在针对所有帐户执行。

如何将单个文件设置为不可删除?如果删除者赋予自己对单个文件的所有权,则允许删除它们是可以接受的,因为这应该足够安全。

我不希望允许域管理员在没有获得文件所有权的情况下删除文件,但如果阻止这些组太困难,可以允许管理员删除文件(本地和域管理员)。迫切需要防止任何非管理员删除任何这些文件。

我的问题因需要“调试详细信息”而被关闭,但没有提及缺少或要求的详细信息。 ???

【问题讨论】:

  • 我投票决定重新提出您的问题,但为了提供一些(希望是建设性的)反馈,我认为通过减少“健谈”、更加专注并且只有一个明确的问题,它仍然可以大大改善.目前它提出了几个隐含/明确的问题:“如何预防......?”,“我做了......?”,“我怎么能......?”,“它可以接受......?”。尝试修改您的帖子,使其恰好包含一个以问号结尾的问题,以便您的问题一目了然。

标签: c# file-permissions acl filesystemobject


【解决方案1】:

经过多次反复试验,我想我找到了解决方案。对删除权限应用“拒绝”是不够的。以下似乎有效。要以这种方式删除文件集,需要具有足够权限的用户来删除拒绝规则。

我获得了所有当前有权访问该文件夹的帐户的列表,添加了几个“知名”帐户,然后遍历这些帐户,删除除 READ 之外的所有权限,然后将 DENY 权限应用于除 READ 之外的所有内容。

获取帐户列表。

    DirectoryInfo dInfo = new DirectoryInfo(dir);
    DirectorySecurity dSec = dInfo.GetAccessControl();
    AuthorizationRuleCollection arc = dSec.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));
    List<string> fileAccounts = new List<string>();
    foreach (FileSystemAccessRule fsar in arc)
    {
        if (!fileAccounts.Contains(fsar.IdentityReference.Value))
            fileAccounts.Add(fsar.IdentityReference.Value);
    }
    foreach (string s in new string[] { "GUEST", "USERS", "DOMAIN USERS", "NETWORK", "Authenticated Users", "SYSTEM", "Everyone" })
    {
        if (!fileAccounts.Contains(s))
            fileAccounts.Add(s);
    }

遍历帐户,删除/添加权限。请注意,并非所有帐户都可能在所有情况下都存在(例如,域/非域帐户),因此我会捕获并丢弃错误。

    FileInfo fi = new FileInfo(fname);
    FileSecurity fsec = fi.GetAccessControl();
    int numSet = 0;
    foreach (string account in fileAccounts)
    {
        try
        {
            fsec.RemoveAccessRule(new FileSystemAccessRule(account, FileSystemRights.Delete, AccessControlType.Allow));
            fsec.RemoveAccessRule(new FileSystemAccessRule(account, FileSystemRights.FullControl, AccessControlType.Allow));
            fsec.RemoveAccessRule(new FileSystemAccessRule(account, FileSystemRights.Modify, AccessControlType.Allow));
            fsec.RemoveAccessRule(new FileSystemAccessRule(account, FileSystemRights.ReadAndExecute, AccessControlType.Allow));
            fsec.RemoveAccessRule(new FileSystemAccessRule(account, FileSystemRights.Write, AccessControlType.Allow));
            fsec.AddAccessRule(new FileSystemAccessRule(account, FileSystemRights.Delete, AccessControlType.Deny));
            fsec.AddAccessRule(new FileSystemAccessRule(account, FileSystemRights.FullControl, AccessControlType.Deny));
            fsec.AddAccessRule(new FileSystemAccessRule(account, FileSystemRights.Modify, AccessControlType.Deny));
            fsec.AddAccessRule(new FileSystemAccessRule(account, FileSystemRights.ReadAndExecute, AccessControlType.Deny));
            fsec.AddAccessRule(new FileSystemAccessRule(account, FileSystemRights.Write, AccessControlType.Deny));
        }
        catch (Exception ex)
        {
            //  log error and continue if necessare - Console.WriteLine(account + ": " + ex.Message);
        }
        numSet++;
    }
    fi.SetAccessControl(fsec);

我怀疑有一种更清洁、更简单的方法可以做到这一点,但至少这可以满足我的需要。

【讨论】:

  • 如果权限是从父文件夹继承的,这是否有效?
  • 是的,但事实证明这在我的服务帐户中处理时无法正常工作。通过在对象/帐户级别创建显式 ACL 规则,这些规则会覆盖继承的 ACL 属性。我在查找使文件只读、可见且不可删除的允许/拒绝规则的确切组合时遇到问题。有关继承和显式文件控件如何工作的详细说明,请搜索“NTFS 文件 acls”并查看那里发布的说明。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-17
  • 2013-06-05
  • 1970-01-01
相关资源
最近更新 更多