仅允许管理员删除文件?

时间:2016-02-10 15:55:21

标签: c#

我正在编写一个C#应用程序,我想设置(在应用程序启动时)权限,这样只有管理员才能删除应用程序使用的文件。所有其他用户都不应该删除它或修改其权限。

应保护文件不受标准文件系统使用的影响(因此除Admin之外,没有人可以删除它)。只有管​​理员应该能够设置文件权限。此外,其他用户应该能够读/写它。

这可能吗?我在这里找到了一些代码示例,但没有一个能够正常工作。 我正在尝试的代码:

FileSecurity fSecurity = File.GetAccessControl("database.sdf");

        AuthorizationRuleCollection rules = fSecurity.GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));
        foreach (AuthorizationRule rule in rules)
        {
            System.Security.Principal.NTAccount account =
                (System.Security.Principal.NTAccount)rule.IdentityReference.Translate(typeof(System.Security.Principal.NTAccount));
            if (account.Value != "BUILTIN\\Administrators")
            {
                fSecurity.AddAccessRule(new FileSystemAccessRule(account.Value, FileSystemRights.Delete, AccessControlType.Deny));
            }
        }

        File.SetAccessControl("database.sdf", fSecurity);    

在以普通用户身份运行时,我是否可以通过应用程序以编程方式配置文件权限和所有者?

谢谢!

PS该文件是SQL Server Compact数据库。

2 个答案:

答案 0 :(得分:1)

在我们开始之前,请允许我这样说:

x[i]

完全没必要

内置的管理员组是well-known security principal,并且保证始终具有相同的安全标识符(System.Security.Principal.NTAccount account = (System.Security.Principal.NTAccount)rule.IdentityReference.Translate(typeof(System.Security.Principal.NTAccount)); if (account.Value != "BUILTIN\\Administrators") ),易于比较对

您当前为恰好具有访问规则的所有主体明确授予拒绝删除的当前程序也可能会适得其反。

想象一下,ACL中已存在具有以下特征的访问规则:

  

身份:每个人都   访问权限:阅读
  控件类型:允许

恭喜!您现在已隐式拒绝所有人删除该文件的权利,包括管理员组。

您想要做的是:

  1. 确保Administrators组是文件的所有者
  2. 删除授予允许删除的所有现有访问规则(显式隐式)
  3. 向管理员组添加允许允许FullControl的单个访问规则
  4. 删除所有继承的规则并保护ACL免于继承
  5. S-1-5-32-544

答案 1 :(得分:0)

使用Mathias'帮助,我找到了我的问题的答案:

try
{
       // Way safer than string comparison against "BUILTIN\\Administrators"
       IdentityReference BuiltinAdministrators = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
       IdentityReference AuthenticatedUsers = new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null);

       FileSecurity FileACL = File.GetAccessControl("database.sdf"); // Grab ACL from file

       if (FileACL.GetOwner(typeof(SecurityIdentifier)) != BuiltinAdministrators) // Check if correct owner is set
       {
             FileACL.SetOwner(BuiltinAdministrators); // If not, make it so!
       }

       foreach (FileSystemAccessRule fsRule in FileACL.GetAccessRules(true, true, typeof(SecurityIdentifier)))
       {
             if ((fsRule.FileSystemRights & FileSystemRights.Delete) == FileSystemRights.Delete ||
                    (fsRule.FileSystemRights & FileSystemRights.ChangePermissions) == FileSystemRights.ChangePermissions) // Check if rule grants delete or change permissions
             {
                  FileACL.RemoveAccessRule(fsRule); // If so, nuke it!
             }
       }

       // Add explicit rules
       FileACL.AddAccessRule(new FileSystemAccessRule(BuiltinAdministrators, FileSystemRights.FullControl, AccessControlType.Allow));
       FileACL.AddAccessRule(new FileSystemAccessRule(AuthenticatedUsers, FileSystemRights.Delete, AccessControlType.Deny));
       FileACL.AddAccessRule(new FileSystemAccessRule(AuthenticatedUsers, FileSystemRights.ChangePermissions, AccessControlType.Deny));
       FileACL.AddAccessRule(new FileSystemAccessRule(AuthenticatedUsers, FileSystemRights.Read, AccessControlType.Allow));
       FileACL.AddAccessRule(new FileSystemAccessRule(AuthenticatedUsers, FileSystemRights.Write, AccessControlType.Allow));

       FileACL.SetAccessRuleProtection(true, false); // Enable protection from inheritance, remove existing inherited rules
       File.SetAccessControl("database.sdf", FileACL); // Write ACL back to file
   }
   catch { }

为了工作,应用程序必须以管理员身份运行一次。

以编程方式设置文件权限对我来说是新的,所以如果有人认为代码可能无法执行其要执行的操作,请更正我。 谢谢!