代码之家  ›  专栏  ›  技术社区  ›  Andy

正在检查.NET中的目录和文件写入权限

  •  74
  • Andy  · 技术社区  · 15 年前

    在我的.NET 2.0应用程序中,我需要检查是否有足够的权限来创建文件并将其写入目录。为此,我有下面的函数,它尝试创建一个文件并向其写入一个字节,然后删除自己以测试权限是否存在。

    我认为最好的检查方法是实际尝试并完成检查,捕获任何发生的异常。不过,对于一般的异常捕获,我并不特别高兴,因此,有没有更好或更容易接受的方法来实现这一点呢?

    private const string TEMP_FILE = "\\tempFile.tmp";
    
    /// <summary>
    /// Checks the ability to create and write to a file in the supplied directory.
    /// </summary>
    /// <param name="directory">String representing the directory path to check.</param>
    /// <returns>True if successful; otherwise false.</returns>
    private static bool CheckDirectoryAccess(string directory)
    {
        bool success = false;
        string fullPath = directory + TEMP_FILE;
    
        if (Directory.Exists(directory))
        {
            try
            {
                using (FileStream fs = new FileStream(fullPath, FileMode.CreateNew, 
                                                                FileAccess.Write))
                {
                    fs.WriteByte(0xff);
                }
    
                if (File.Exists(fullPath))
                {
                    File.Delete(fullPath);
                    success = true;
                }
            }
            catch (Exception)
            {
                success = false;
            }
        }
    
    8 回复  |  直到 6 年前
        1
  •  21
  •   Community Erin Dees    7 年前

    答案由 Richard Jason 有点方向正确。但是你应该做的是 computing the effective permissions 用于运行代码的用户标识。例如,上面的例子都不能正确说明组成员身份。

    我很确定 Keith Brown 他身上有一些密码 wiki version (此时脱机)的 The .NET Developers Guide to Windows Security . 这也在他的 Programming Windows Security 书。

    计算有效的权限并不是为了胆小的人,而您试图创建文件并捕获抛出的安全异常的代码可能是阻力最小的途径。

        2
  •  46
  •   Οurous richardwiden    10 年前

    Directory.GetAcessControl(path) 做你想要的。

    public static bool HasWritePermissionOnDir(string path)
    {
        var writeAllow = false;
        var writeDeny = false;
        var accessControlList = Directory.GetAccessControl(path);
        if (accessControlList == null)
            return false;
        var accessRules = accessControlList.GetAccessRules(true, true, 
                                    typeof(System.Security.Principal.SecurityIdentifier));
        if (accessRules ==null)
            return false;
    
        foreach (FileSystemAccessRule rule in accessRules)
        {
            if ((FileSystemRights.Write & rule.FileSystemRights) != FileSystemRights.Write) 
                continue;
    
            if (rule.AccessControlType == AccessControlType.Allow)
                writeAllow = true;
            else if (rule.AccessControlType == AccessControlType.Deny)
                writeDeny = true;
        }
    
        return writeAllow && !writeDeny;
    }
    

    (FileSystemRights.Write & rights) == FileSystemRights.Write 正在使用名为“标志”btw的东西,如果您不知道它是什么,那么您应该在上阅读:)

        3
  •  31
  •   Olivier Jacot-Descombes    7 年前

    Deny 优先于 Allow . 本地规则优先于继承的规则。我见过许多解决方案(包括这里显示的一些答案),但没有一个解决方案考虑到规则是否 继承 或者没有。因此,我建议采用以下方法来考虑规则继承(整齐地包装成一个类):

    public class CurrentUserSecurity
    {
        WindowsIdentity _currentUser;
        WindowsPrincipal _currentPrincipal;
    
        public CurrentUserSecurity()
        {
            _currentUser = WindowsIdentity.GetCurrent();
            _currentPrincipal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
        }
    
        public bool HasAccess(DirectoryInfo directory, FileSystemRights right)
        {
            // Get the collection of authorization rules that apply to the directory.
            AuthorizationRuleCollection acl = directory.GetAccessControl()
                .GetAccessRules(true, true, typeof(SecurityIdentifier));
            return HasFileOrDirectoryAccess(right, acl);
        }
    
        public bool HasAccess(FileInfo file, FileSystemRights right)
        {
            // Get the collection of authorization rules that apply to the file.
            AuthorizationRuleCollection acl = file.GetAccessControl()
                .GetAccessRules(true, true, typeof(SecurityIdentifier));
            return HasFileOrDirectoryAccess(right, acl);
        }
    
        private bool HasFileOrDirectoryAccess(FileSystemRights right,
                                              AuthorizationRuleCollection acl)
        {
            bool allow = false;
            bool inheritedAllow = false;
            bool inheritedDeny = false;
    
            for (int i = 0; i < acl.Count; i++) {
                var currentRule = (FileSystemAccessRule)acl[i];
                // If the current rule applies to the current user.
                if (_currentUser.User.Equals(currentRule.IdentityReference) ||
                    _currentPrincipal.IsInRole(
                                    (SecurityIdentifier)currentRule.IdentityReference)) {
    
                    if (currentRule.AccessControlType.Equals(AccessControlType.Deny)) {
                        if ((currentRule.FileSystemRights & right) == right) {
                            if (currentRule.IsInherited) {
                                inheritedDeny = true;
                            } else { // Non inherited "deny" takes overall precedence.
                                return false;
                            }
                        }
                    } else if (currentRule.AccessControlType
                                                      .Equals(AccessControlType.Allow)) {
                        if ((currentRule.FileSystemRights & right) == right) {
                            if (currentRule.IsInherited) {
                                inheritedAllow = true;
                            } else {
                                allow = true;
                            }
                        }
                    }
                }
            }
    
            if (allow) { // Non inherited "allow" takes precedence over inherited rules.
                return true;
            }
            return inheritedAllow && !inheritedDeny;
        }
    }
    

    但是,我的经验是,这并不总是在远程计算机上工作,因为您并不总是有权查询那里的文件访问权限。在这种情况下,解决方案是尝试;甚至可能只是尝试创建一个临时文件,如果您需要在处理“真实”文件之前知道访问权限的话。

        4
  •  18
  •   Bryce Wagner    12 年前

    kev对这个问题的公认答案实际上并没有给出任何代码,它只是指向我无法访问的其他资源。这是我对这个功能的最好尝试。它实际上检查它所查看的权限是否为“写”权限,以及当前用户是否属于适当的组。

    对于网络路径或其他方面,它可能不完整,但就我而言,它已经足够好了,可以检查“程序文件”下的本地配置文件的可写性:

    using System.Security.Principal;
    using System.Security.AccessControl;
    
    private static bool HasWritePermission(string FilePath)
    {
        try
        {
            FileSystemSecurity security;
            if (File.Exists(FilePath))
            {
                security = File.GetAccessControl(FilePath);
            }
            else
            {
                security = Directory.GetAccessControl(Path.GetDirectoryName(FilePath));
            }
            var rules = security.GetAccessRules(true, true, typeof(NTAccount));
    
            var currentuser = new WindowsPrincipal(WindowsIdentity.GetCurrent());
            bool result = false;
            foreach (FileSystemAccessRule rule in rules)
            {
                if (0 == (rule.FileSystemRights &
                    (FileSystemRights.WriteData | FileSystemRights.Write)))
                {
                    continue;
                }
    
                if (rule.IdentityReference.Value.StartsWith("S-1-"))
                {
                    var sid = new SecurityIdentifier(rule.IdentityReference.Value);
                    if (!currentuser.IsInRole(sid))
                    {
                        continue;
                    }
                }
                else
                {
                    if (!currentuser.IsInRole(rule.IdentityReference.Value))
                    {
                        continue;
                    }
                }
    
                if (rule.AccessControlType == AccessControlType.Deny)
                    return false;
                if (rule.AccessControlType == AccessControlType.Allow)
                    result = true;
            }
            return result;
        }
        catch
        {
            return false;
        }
    }
    
        5
  •  5
  •   mjalil    10 年前

    IMO,您需要像往常一样使用这些目录,但在使用前不检查权限,而是提供正确的方法来处理未授权的AccessException并做出相应的反应。这种方法更简单,更不容易出错。

        6
  •  3
  •   SteveC    11 年前

    尝试使用我刚才编写的C片段:

    using System;
    using System.IO;
    using System.Security.AccessControl;
    using System.Security.Principal;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                string directory = @"C:\downloads";
    
                DirectoryInfo di = new DirectoryInfo(directory);
    
                DirectorySecurity ds = di.GetAccessControl();
    
                foreach (AccessRule rule in ds.GetAccessRules(true, true, typeof(NTAccount)))
                {
                    Console.WriteLine("Identity = {0}; Access = {1}", 
                                  rule.IdentityReference.Value, rule.AccessControlType);
                }
            }
        }
    }
    

    here's 你也可以参考一下。我的代码可能会让您了解如何在尝试写入目录之前检查权限。

        7
  •  0
  •   Mulder2008    6 年前

    根据此链接: http://www.authorcode.com/how-to-check-file-permission-to-write-in-c/

    使用现有的类SecurityManager更容易

    string FileLocation = @"C:\test.txt";
    FileIOPermission writePermission = new FileIOPermission(FileIOPermissionAccess.Write, FileLocation);
    if (SecurityManager.IsGranted(writePermission))
    {
      // you have permission
    }
    else
    {
     // permission is required!
    }
    

    但它似乎已经过时了,建议使用permissionset。

    [Obsolete("IsGranted is obsolete and will be removed in a future release of the .NET Framework.  Please use the PermissionSet property of either AppDomain or Assembly instead.")]
    
        8
  •  -1
  •   user2285236    8 年前
    private static void GrantAccess(string file)
            {
                bool exists = System.IO.Directory.Exists(file);
                if (!exists)
                {
                    DirectoryInfo di = System.IO.Directory.CreateDirectory(file);
                    Console.WriteLine("The Folder is created Sucessfully");
                }
                else
                {
                    Console.WriteLine("The Folder already exists");
                }
                DirectoryInfo dInfo = new DirectoryInfo(file);
                DirectorySecurity dSecurity = dInfo.GetAccessControl();
                dSecurity.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), FileSystemRights.FullControl, InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit, PropagationFlags.NoPropagateInherit, AccessControlType.Allow));
                dInfo.SetAccessControl(dSecurity);
    
            }