如何防止任何用户删除文件

问题描述 投票:-2回答:1

问题:至少在没有管理员权限的情况下,需要防止单个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个回答
0
投票
经过更多的反复试验,我认为我找到了解决方案。仅对删除权限应用“拒绝”是不够的。以下似乎有效。要以这种方式删除文件集,需要具有足够特权的用户才能删除“拒绝”规则。

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

获取帐户列表。

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);

我怀疑有更干净,更简单的方法来执行此操作,但是至少这可以满足我的需要。
© www.soinside.com 2019 - 2024. All rights reserved.