首页 文章

如何检查写入目录或文件的权限?

提问于
浏览
56

我有一个程序,使用类似下面的方法将一些数据写入文件 .

public void ExportToFile(string filename)
{
     using(FileStream fstream = new FileStream(filename,FileMode.Create))
     using (TextWriter writer = new StreamWriter(fstream))
     {
         // try catch block for write permissions 
         writer.WriteLine(text);


     }
}

运行程序时出现错误:

未处理的异常:System.UnauthorizedAccessException:拒绝访问路径'mypath' . 在System.IO .__ Error.WinIOError(Int32 errorCode,String maybeFullPath)at System.IO.FileStream.Init(String path,FileMode mode,FileAccess access,nt32 rights,Boolean useRights,FileShare share,Int32 bufferSize,FileOptions ptions,SECURITY_ATTRIBUTES secAttrs System.IO.FileStream..ctor中的,String msgPath,Boolean bFromProxy)(字符串路径,FileMode模式,FileAccess访问FileShare共享,Int32 bufferSize,FileOptions选项,字符串msgPath,Boolea bFromProxy)

问题:我需要使用哪些代码来获取此信息以及如何授予访问权限?

8 回答

  • 63

    它是MaxOvrdrv的Code的固定版本 .

    public static bool IsReadable(this DirectoryInfo di)
    {
        AuthorizationRuleCollection rules;
        WindowsIdentity identity;
        try
        {
            rules = di.GetAccessControl().GetAccessRules(true, true, typeof(SecurityIdentifier));
            identity = WindowsIdentity.GetCurrent();
        }
        catch (UnauthorizedAccessException uae)
        {
            Debug.WriteLine(uae.ToString());
            return false;
        }
    
        bool isAllow = false;
        string userSID = identity.User.Value;
    
        foreach (FileSystemAccessRule rule in rules)
        {
            if (rule.IdentityReference.ToString() == userSID || identity.Groups.Contains(rule.IdentityReference))
            {
                if ((rule.FileSystemRights.HasFlag(FileSystemRights.Read) ||
                    rule.FileSystemRights.HasFlag(FileSystemRights.ReadAttributes) ||
                    rule.FileSystemRights.HasFlag(FileSystemRights.ReadData)) && rule.AccessControlType == AccessControlType.Deny)
                    return false;
                else if ((rule.FileSystemRights.HasFlag(FileSystemRights.Read) &&
                    rule.FileSystemRights.HasFlag(FileSystemRights.ReadAttributes) &&
                    rule.FileSystemRights.HasFlag(FileSystemRights.ReadData)) && rule.AccessControlType == AccessControlType.Allow)
                    isAllow = true;
    
            }
        }
        return isAllow;
    }
    
    public static bool IsWriteable(this DirectoryInfo me)
    {
        AuthorizationRuleCollection rules;
        WindowsIdentity identity;
        try
        {
            rules = me.GetAccessControl().GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));
            identity = WindowsIdentity.GetCurrent();
        }
        catch (UnauthorizedAccessException uae)
        {
            Debug.WriteLine(uae.ToString());
            return false;
        }
    
        bool isAllow = false;
        string userSID = identity.User.Value;
    
        foreach (FileSystemAccessRule rule in rules)
        {
            if (rule.IdentityReference.ToString() == userSID || identity.Groups.Contains(rule.IdentityReference))
            {
                if ((rule.FileSystemRights.HasFlag(FileSystemRights.Write) ||
                    rule.FileSystemRights.HasFlag(FileSystemRights.WriteAttributes) ||
                    rule.FileSystemRights.HasFlag(FileSystemRights.WriteData) ||
                    rule.FileSystemRights.HasFlag(FileSystemRights.CreateDirectories) ||
                    rule.FileSystemRights.HasFlag(FileSystemRights.CreateFiles)) && rule.AccessControlType == AccessControlType.Deny)
                    return false;
                else if ((rule.FileSystemRights.HasFlag(FileSystemRights.Write) &&
                    rule.FileSystemRights.HasFlag(FileSystemRights.WriteAttributes) &&
                    rule.FileSystemRights.HasFlag(FileSystemRights.WriteData) &&
                    rule.FileSystemRights.HasFlag(FileSystemRights.CreateDirectories) &&
                    rule.FileSystemRights.HasFlag(FileSystemRights.CreateFiles)) && rule.AccessControlType == AccessControlType.Allow)
                    isAllow = true;
    
            }
        }
        return isAllow;
    }
    
  • 30

    UPDATE:

    修改了基于this answer的代码,以摆脱过时的方法 .

    您可以使用Security命名空间来检查:

    public void ExportToFile(string filename)
    {
        var permissionSet = new PermissionSet(PermissionState.None);    
        var writePermission = new FileIOPermission(FileIOPermissionAccess.Write, filename);
        permissionSet.AddPermission(writePermission);
    
        if (permissionSet.IsSubsetOf(AppDomain.CurrentDomain.PermissionSet))
        {
            using (FileStream fstream = new FileStream(filename, FileMode.Create))
            using (TextWriter writer = new StreamWriter(fstream))
            {
                // try catch block for write permissions 
                writer.WriteLine("sometext");
    
    
            }
        }
        else
        {
            //perform some recovery action here
        }
    
    }
    

    获得这些许可,你将不得不要求用户以某种方式为你做这件事 . 如果你能以编程方式做到这一点,那么我们都会遇到麻烦;)

  • 8

    对不起,但以前的解决方案都没有帮助我 . 我需要检查双方:SecurityManager和SO权限 . 我已经从Josh代码和iain答案中学到了很多东西,但我担心我需要使用Rakesh代码(也要感谢他) . 只有一个错误:我发现他只检查允许而不是拒绝拒绝权限 . 所以我的建议是:

    string folder;
            AuthorizationRuleCollection rules;
            try {
                rules = Directory.GetAccessControl(folder)
                    .GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));
            } catch(Exception ex) { //Posible UnauthorizedAccessException
                throw new Exception("No permission", ex);
            }
    
            var rulesCast = rules.Cast<FileSystemAccessRule>();
            if(rulesCast.Any(rule => rule.AccessControlType == AccessControlType.Deny)
                || !rulesCast.Any(rule => rule.AccessControlType == AccessControlType.Allow))
                throw new Exception("No permission");
    
            //Here I have permission, ole!
    
  • 4

    由于这还没有结束,我想为任何想要为他们正常工作的人提交一个新条目...使用我在这里找到的内容的合并,以及使用DirectoryServices调试代码本身并找到正确的代码使用,这里是我发现在任何情况下都适合我...注意我的解决方案扩展DirectoryInfo对象...:

    public static bool IsReadable(this DirectoryInfo me)
        {
    
            AuthorizationRuleCollection rules;
            WindowsIdentity identity;
            try
            {
                rules = me.GetAccessControl().GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));
                identity = WindowsIdentity.GetCurrent();
            }
            catch (Exception ex)
            { //Posible UnauthorizedAccessException
                return false;
            }
    
            bool isAllow=false;
            string userSID = identity.User.Value;
    
            foreach (FileSystemAccessRule rule in rules)
            {
                if (rule.IdentityReference.ToString() == userSID || identity.Groups.Contains(rule.IdentityReference))
                {
                    if ((rule.FileSystemRights.HasFlag(FileSystemRights.Read) ||
                        rule.FileSystemRights.HasFlag(FileSystemRights.ReadAndExecute) ||
                        rule.FileSystemRights.HasFlag(FileSystemRights.ReadAttributes) ||
                        rule.FileSystemRights.HasFlag(FileSystemRights.ReadData) ||
                        rule.FileSystemRights.HasFlag(FileSystemRights.ReadExtendedAttributes) ||
                        rule.FileSystemRights.HasFlag(FileSystemRights.ReadPermissions)) && rule.AccessControlType == AccessControlType.Deny)
                        return false;
                    else if ((rule.FileSystemRights.HasFlag(FileSystemRights.Read) ||
                        rule.FileSystemRights.HasFlag(FileSystemRights.ReadAndExecute) ||
                        rule.FileSystemRights.HasFlag(FileSystemRights.ReadAttributes) ||
                        rule.FileSystemRights.HasFlag(FileSystemRights.ReadData) ||
                        rule.FileSystemRights.HasFlag(FileSystemRights.ReadExtendedAttributes) ||
                        rule.FileSystemRights.HasFlag(FileSystemRights.ReadPermissions)) && rule.AccessControlType == AccessControlType.Allow)
                        isAllow = true;
                }
            }
    
            return isAllow;
        }
    
        public static bool IsWriteable(this DirectoryInfo me)
        {
            AuthorizationRuleCollection rules;
            WindowsIdentity identity;
            try
            {
                rules = me.GetAccessControl().GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));
                identity = WindowsIdentity.GetCurrent();
            }
            catch (Exception ex)
            { //Posible UnauthorizedAccessException
                return false;
            }
    
            bool isAllow = false;
            string userSID = identity.User.Value;
    
            foreach (FileSystemAccessRule rule in rules)
            {
                if (rule.IdentityReference.ToString() == userSID || identity.Groups.Contains(rule.IdentityReference))
                {
                    if ((rule.FileSystemRights.HasFlag(FileSystemRights.Write) ||
                        rule.FileSystemRights.HasFlag(FileSystemRights.WriteAttributes) ||
                        rule.FileSystemRights.HasFlag(FileSystemRights.WriteData) ||
                        rule.FileSystemRights.HasFlag(FileSystemRights.WriteExtendedAttributes) ||
                        rule.FileSystemRights.HasFlag(FileSystemRights.CreateDirectories) ||
                        rule.FileSystemRights.HasFlag(FileSystemRights.CreateFiles)) && rule.AccessControlType == AccessControlType.Deny)
                        return false;
                    else if ((rule.FileSystemRights.HasFlag(FileSystemRights.Write) ||
                        rule.FileSystemRights.HasFlag(FileSystemRights.WriteAttributes) ||
                        rule.FileSystemRights.HasFlag(FileSystemRights.WriteData) ||
                        rule.FileSystemRights.HasFlag(FileSystemRights.WriteExtendedAttributes) ||
                        rule.FileSystemRights.HasFlag(FileSystemRights.CreateDirectories) ||
                        rule.FileSystemRights.HasFlag(FileSystemRights.CreateFiles)) && rule.AccessControlType == AccessControlType.Allow)
                        isAllow = true;
                }
            }
    
            return me.IsReadable() && isAllow;
        }
    
  • 2

    您可以尝试使用以下代码块来检查目录是否具有写入权限 .

    它检查FileSystemAccessRule .

    string directoryPath = "C:\\XYZ"; //folderBrowserDialog.SelectedPath;
               bool isWriteAccess = false;
               try
               {
                  AuthorizationRuleCollection collection = Directory.GetAccessControl(directoryPath).GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));
                  foreach (FileSystemAccessRule rule in collection)
                  {
                     if (rule.AccessControlType == AccessControlType.Allow)
                     {
                        isWriteAccess = true;
                        break;
                     }
                  }
               }
               catch (UnauthorizedAccessException ex)
               {
                  isWriteAccess = false;
               }
               catch (Exception ex)
               {
                  isWriteAccess = false;
               }
               if (!isWriteAccess)
               {
                 //handle notifications                 
               }
    
  • 3

    哇......这个帖子中有很多低级别的安全代码 - 其中大部分对我来说都不起作用 - 尽管我在这个过程中学到了很多东西 . 我学到的一件事是,大多数代码都不适合寻求每个用户访问权限的应用程序 - 管理员希望以编程方式更改权限,正如已经指出的那样,这不是一件好事 . 作为开发人员,我不能使用"easy way out" - 以管理员身份运行 - 我不是运行代码的机器上的人,也不是我的用户 - 所以,就像这些解决方案一样聪明 - 他们是不是我的情况,也可能不是大多数普通开发人员 .

    像大多数这类问题的海报一样 - 我最初觉得它也是“hackey” - 我已经决定尝试它并且让可能的例外确切地告诉你用户的权利是什么 - 因为我得到的信息并没有告诉我实际上是什么权利 . 下面的代码 - 做了 .

    Private Function CheckUserAccessLevel(folder As String) As Boolean
    Try
      Dim newDir As String = String.Format("{0}{1}{2}",
                                           folder,
                                           If(folder.EndsWith("\"),
                                              "",
                                              "\"),
                                           "LookWhatICanDo")
      Dim lookWhatICanDo = Directory.CreateDirectory(newDir)
    
      Directory.Delete(newDir)
      Return True
    
    Catch ex As Exception
      Return False
    End Try
    

    结束功能

  • 0

    当您的代码执行以下操作时:

    • 检查当前用户是否有权执行某些操作 .

    • 执行需要检查1中的权利的操作 .

    您存在权限在1和2之间变化的风险,因为您无法预测在运行时系统上还会发生什么 . 因此,即使您之前已经检查过权限,您的代码也应该处理抛出UnauthorisedAccessException的情况 .

    请注意,SecurityManager类用于检查CAS权限,并且实际上不会向操作系统检查当前用户是否具有对指定位置的写访问权(通过ACL和ACE) . 因此,对于本地运行的应用程序,IsGranted将始终返回true .

    Example (派生自Josh's example):

    //1. Provide early notification that the user does not have permission to write.
    FileIOPermission writePermission = new FileIOPermission(FileIOPermissionAccess.Write, filename);
    if(!SecurityManager.IsGranted(writePermission))
    {
        //No permission. 
        //Either throw an exception so this can be handled by a calling function
        //or inform the user that they do not have permission to write to the folder and return.
    }
    
    //2. Attempt the action but handle permission changes.
    try
    {
        using (FileStream fstream = new FileStream(filename, FileMode.Create))
        using (TextWriter writer = new StreamWriter(fstream))
        {
            writer.WriteLine("sometext");
        }
    }
    catch (UnauthorizedAccessException ex)
    {
        //No permission. 
        //Either throw an exception so this can be handled by a calling function
        //or inform the user that they do not have permission to write to the folder and return.
    }
    

    这很棘手,并且尝试以编程方式根据原始ACL(通过System.Security.AccessControl类提供的所有内容)从文件夹中计算有效权限 . Stack Overflow和更广泛的网站上的其他答案建议尝试执行操作以了解是否允许权限 . This post总结了实现权限计算所需的内容,应该足以让您无法执行此操作 .

  • 6

    这些都不适合我......他们回归真实,即使他们不是 . 问题是,您必须针对当前进程用户权限测试可用权限,此测试文件创建权限,只需将FileSystemRights子句更改为“Write”以测试写入权限 .

    /// <summary>
    /// Test a directory for create file access permissions
    /// </summary>
    /// <param name="DirectoryPath">Full directory path</param>
    /// <returns>State [bool]</returns>
    public static bool DirectoryCanCreate(string DirectoryPath)
    {
        if (string.IsNullOrEmpty(DirectoryPath)) return false;
    
        try
        {
            AuthorizationRuleCollection rules = Directory.GetAccessControl(DirectoryPath).GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));
            WindowsIdentity identity = WindowsIdentity.GetCurrent();
    
            foreach (FileSystemAccessRule rule in rules)
            {
                if (identity.Groups.Contains(rule.IdentityReference))
                {
                    if ((FileSystemRights.CreateFiles & rule.FileSystemRights) == FileSystemRights.CreateFiles)
                    {
                        if (rule.AccessControlType == AccessControlType.Allow)
                            return true;
                    }
                }
            }
        }
        catch {}
        return false;
    }
    

相关问题