简体   繁体   English

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

[英]How do you check for permissions to write to a directory or file?

I got a program that writes some data to a file using a method like the one below. 我有一个程序,使用如下所示的方法将一些数据写入文件。


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


     }
}

When running the program I get an error: 运行程序时出现错误:

Unhandled Exception: System.UnauthorizedAccessException: Access to the path 'mypath' is denied. 未处理的异常:System.UnauthorizedAccessException:拒绝访问路径'mypath'。 at 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, String msgPath, Boolean bFromProxy) at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolea bFromProxy) 在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 String msgPath,Boolean bFromProxy(字符串路径,FileMode模式,FileAccess访问FileShare共享,Int32 bufferSize,FileOptions选项,字符串msgPath,Boolea bFromProxy)

Question: What code do I need to catch this and how do I grant the access? 问题:我需要使用哪些代码来获取此信息以及如何授予访问权限?

UPDATE: 更新:

Modified the code based on this answer to get rid of obsolete methods. 修改了基于此答案的代码,以摆脱过时的方法。

You can use the Security namespace to check this: 您可以使用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
    }

}

As far as getting those permission, you are going to have to ask the user to do that for you somehow. 至于获得这些许可,您将不得不要求用户以某种方式为您执行此操作。 If you could programatically do this, then we would all be in trouble ;) 如果您可以以编程方式执行此操作,那么我们都会遇到麻烦;)

When your code does the following: 当您的代码执行以下操作时:

  1. Checks the current user has permission to do something. 检查当前用户是否有权执行某些操作。
  2. Carries out the action that needs the entitlements checked in 1. 执行需要检查1中的权利的操作。

You run the risk that the permissions change between 1 and 2 because you can't predict what else will be happening on the system at runtime. 您存在权限在12之间变化的风险,因为您无法预测在运行时系统上还会发生什么。 Therefore, your code should handle the situation where an UnauthorisedAccessException is thrown even if you have previously checked permissions. 因此,即使您之前已经检查过权限,您的代码也应该处理抛出UnauthorisedAccessException的情况。

Note that the SecurityManager class is used to check CAS permissions and doesn't actually check with the OS whether the current user has write access to the specified location (through ACLs and ACEs). 请注意, SecurityManager类用于检查CAS权限,并且实际上不会检查当前用户是否具有对指定位置的写访问权(通过ACL和ACE)。 As such, IsGranted will always return true for locally running applications. 因此,对于本地运行的应用程序, IsGranted将始终返回true。

Example (derived from Josh's example ): 示例 (源自Josh的示例 ):

//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.
}

It's tricky and not recommended to try to programatically calculate the effective permissions from the folder based on the raw ACLs (which are all that are available through the System.Security.AccessControl classes). 这很棘手, 不建议尝试以编程方式根据原始ACL(通过System.Security.AccessControl类提供的所有内容)从文件夹中计算有效权限。 Other answers on Stack Overflow and the wider web recommend trying to carry out the action to know whether permission is allowed. Stack Overflow和更广泛的网站上的其他答案建议尝试执行操作以了解是否允许权限。 This post sums up what's required to implement the permission calculation and should be enough to put you off from doing this. 这篇文章总结了实现权限计算所需的内容,应该足以让您无法执行此操作。

Its a fixed version of MaxOvrdrv's Code . 它是MaxOvrdrv 代码的固定版本。

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

Sorry, but none of the previous solutions helped me. 对不起,但以前的解决方案都没有帮助我。 I need to check both sides: SecurityManager and SO permissions. 我需要检查双方:SecurityManager和SO权限。 I have learned a lot with Josh code and with iain answer, but I'm afraid I need to use Rakesh code (also thanks to him). 我已经从Josh代码和iain答案中学到了很多,但我担心我需要使用Rakesh代码(也要感谢他)。 Only one bug: I found that he only checks for Allow and not for Deny permissions. 只有一个bug:我发现他只检查Allow而不是Deny权限。 So my proposal is: 所以我的提议是:

        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!

Since this isn't closed, i would like to submit a new entry for anyone looking to have something working properly for them... using an amalgamation of what i found here, as well as using DirectoryServices to debug the code itself and find the proper code to use, here's what i found that works for me in every situation... note that my solution extends DirectoryInfo object... : 由于这还没有结束,我想为任何想要为他们正常工作的人提交一个新条目...使用我在这里找到的内容的合并,以及使用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;
    }

None of these worked for me.. they return as true, even when they aren't. 这些都不适合我......他们的回归是真的,即使他们不是。 The problem is, you have to test the available permission against the current process user rights, this tests for file creation rights, just change the FileSystemRights clause to 'Write' to test write access.. 问题是,您必须针对当前进程用户权限测试可用权限,此测试文件创建权限,只需将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;
}

You can try following code block to check if the directory is having Write Access. 您可以尝试以下代码块来检查目录是否具有写访问权限。

It checks the FileSystemAccessRule. 它检查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                 
           }

Wow...there is a lot of low-level security code in this thread -- most of which did not work for me, either -- although I learned a lot in the process. 哇...这个帖子中有很多低级安全代码 - 其中大部分也不适用于我 - 尽管我在这个过程中学到了很多东西。 One thing that I learned is that most of this code is not geared to applications seeking per user access rights -- it is for Administrators wanting to alter rights programmatically, which -- as has been pointed out -- is not a good thing. 我学到的一件事是,大多数代码都不适合寻求每个用户访问权限的应用程序 - 管理员希望以编程方式更改权限,正如已经指出的那样,这不是一件好事。 As a developer, I cannot use the "easy way out" -- by running as Administrator -- which -- I am not one on the machine that runs the code, nor are my users -- so, as clever as these solutions are -- they are not for my situation, and probably not for most rank and file developers, either. 作为开发人员,我不能使用“简单的方法” - 通过以管理员身份运行 - 我不是运行代码的机器上的人,也不是我的用户 - 所以,这些解决方案是聪明的 - 它们不适用于我的情况,也可能不适用于大多数普通级别的开发人员。

Like most posters of this type of question -- I initially felt it was "hackey", too -- I have since decided that it is perfectly alright to try it and let the possible exception tell you exactly what the user's rights are -- because the information I got did not tell me what the rights actually were. 像大多数这类问题的海报一样 - 我最初觉得它也是“hackey” - 我已经决定尝试它并且让可能的例外确切地告诉你用户的权利是什么 - 因为我得到的信息并没有告诉我实际上是什么权利。 The code below -- did. 下面的代码 - 做了。

  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

End Function 结束功能

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何更改文件权限以阻止 Vista 写入 VirtualStore 目录中的文件? - How do you change file permissions to stop Vista from writing to a file in the VirtualStore directory? 文件权限不会继承目录权限 - File permissions do not inherit directory permissions 检查 .NET 中的目录和文件写入权限 - Checking for directory and file write permissions in .NET 如何使用 C# 检查 LocalSystem 帐户是否具有对特定本地目录的读/写权限? - How to check if LocalSystem account has read/write permissions to a specific local directory using C#? 您如何使用StreamWriter写入文件 - How do you use StreamWriter to write to a file 向 web 应用程序添加通用内容虚拟目录时如何做安全权限? - How do you do security permissions when adding a common content virtual directory to a web application? 以管理员身份运行,如何检查某些Windows帐户是否有权读取目录? - Running as Admin, How do I check if some windows account has permissions to read a directory? 如何以编程方式检查.NET中的EFFECTIVE删除(修改)或写入权限? - How do I programmatically check EFFECTIVE delete (modify) or write permissions in .NET? C#-检查UNC文件共享上的文件夹写权限(Winforms) - C# - Check Folder Write Permissions On UNC File Share (Winforms) 如何将ListBox项目写入文本文件? - How do you write ListBox items to a text file?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM