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

时间:2020-03-06 14:41:46  来源:igfitidea点击:

我有一个程序可以使用以下方法将一些数据写入文件。

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

     }
}

运行程序时出现错误:

Unhandled Exception: System.UnauthorizedAccessException: Access to the path 'mypath' is denied.
     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)

问题:我需要什么代码才能捕获此错误,如何授予访问权限?

解决方案

更新:

根据此答案修改了代码,以摆脱过时的方法。

我们可以使用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
    }

}

就获得那些许可而言,我们将必须要求用户以某种方式为我们执行此操作。如果我们可以通过编程方式执行此操作,那么我们都会有麻烦;)

当代码执行以下操作时:

  • 检查当前用户是否有权执行某项操作。
  • 执行需要检入1的权利的操作。

我们冒着权限在1到2之间变化的风险,因为我们无法预测运行时系统上还会发生什么。因此,即使我们先前已经检查了权限,代码也应该处理引发UnauthorizedAccessException的情况。

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

示例(源自乔希的示例):

//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类获得的所有ACL)以编程方式从文件夹中计算有效权限。有关Stack Overflow和更广泛的网络的其他答案,建议尝试执行该操作以了解是否允许权限。这篇文章总结了实现权限计算所需的知识,并且应该足以使我们摆脱此限制。

我们可以尝试使用以下代码块来检查目录是否具有写访问权限。

它检查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                 
           }

抱歉,以前的解决方案都没有帮助我。我需要检查双方: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!