我需要测试用户是否可以在实际尝试这样做之前写入文件夹。

我已经实现了以下方法(在c# 2.0中),它尝试使用Directory.GetAccessControl()方法检索文件夹的安全权限。

private bool hasWriteAccessToFolder(string folderPath)
{
    try
    {
        // Attempt to get a list of security permissions from the folder. 
        // This will raise an exception if the path is read only or do not have access to view the permissions. 
        System.Security.AccessControl.DirectorySecurity ds = Directory.GetAccessControl(folderPath);
        return true;
    }
    catch (UnauthorizedAccessException)
    {
        return false;
    }
}

当我在谷歌上搜索如何测试写访问权限时,没有这样的结果,而且在Windows中测试权限看起来非常复杂。我担心我过于简化了事情,这个方法并不健壮,尽管它似乎确实有效。

我测试当前用户是否具有写访问权限的方法是否正确?


当前回答

例如,对于所有用户(内置用户),此方法工作良好-享受。

public static bool HasFolderWritePermission(string destDir)
{
   if(string.IsNullOrEmpty(destDir) || !Directory.Exists(destDir)) return false;
   try
   {
      DirectorySecurity security = Directory.GetAccessControl(destDir);
      SecurityIdentifier users = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
      foreach(AuthorizationRule rule in security.GetAccessRules(true, true, typeof(SecurityIdentifier)))
      {
          if(rule.IdentityReference == users)
          {
             FileSystemAccessRule rights = ((FileSystemAccessRule)rule);
             if(rights.AccessControlType == AccessControlType.Allow)
             {
                    if(rights.FileSystemRights == (rights.FileSystemRights | FileSystemRights.Modify)) return true;
             }
          }
       }
       return false;
    }
    catch
    {
        return false;
    }
}

其他回答

在代码中有一个潜在的竞争条件——如果用户在检查时拥有写入文件夹的权限,但在用户实际写入文件夹之前,该权限被撤销,会发生什么情况?写入操作将抛出一个异常,您需要捕获并处理该异常。所以最初的检查是没有意义的。您也可以只执行写入并处理任何异常。这是你的情况的标准模式。

试试这个:

try
{
    DirectoryInfo di = new DirectoryInfo(path);
    DirectorySecurity acl = di.GetAccessControl();
    AuthorizationRuleCollection rules = acl.GetAccessRules(true, true, typeof(NTAccount));

    WindowsIdentity currentUser = WindowsIdentity.GetCurrent();
    WindowsPrincipal principal = new WindowsPrincipal(currentUser);
    foreach (AuthorizationRule rule in rules)
    {
        FileSystemAccessRule fsAccessRule = rule as FileSystemAccessRule;
        if (fsAccessRule == null)
            continue;

        if ((fsAccessRule.FileSystemRights & FileSystemRights.WriteData) > 0)
        {
            NTAccount ntAccount = rule.IdentityReference as NTAccount;
            if (ntAccount == null)
            {
                continue;
            }

            if (principal.IsInRole(ntAccount.Value))
            {
                Console.WriteLine("Current user is in role of {0}, has write access", ntAccount.Value);
                continue;
            }
            Console.WriteLine("Current user is not in role of {0}, does not have write access", ntAccount.Value);                        
        }
    }
}
catch (UnauthorizedAccessException)
{
    Console.WriteLine("does not have write access");
}

这应该是您所需要的全部内容,据我所知,您只需要捕获一个异常。

private static readonly byte[] TestArray = new byte[]{
    69, 70, 71, 72
};

private static bool IsFolderAccessible(string path) {
    var temp_path = Path.Combine(path, Path.GetRandomFileName());

    try {
        using (var file = File.Create(temp_path, TestArray.Length, FileOptions.DeleteOnClose)) {
            file.Write(TestArray, 0, TestArray.Length);
        }

        return true;
    } catch (UnauthorizedAccessException ex) {
        Log.Warn($"Error accessing file {temp_path}", ex);

        return false;
    }
}

这里的大多数答案都不检查写访问。它只是检查用户/组是否可以“读取权限”(读取文件/目录的ACE列表)。

此外,遍历ACE并检查它是否与安全标识符匹配也不起作用,因为用户可能是他可能获得/失去特权的组的成员。更糟糕的是嵌套组。

我知道这是一个旧的线程,但有一个更好的方式为任何人现在看。

如果用户具有Read Permission权限为,则可以使用Authz API检查有效访问。

https://learn.microsoft.com/en-us/windows/win32/secauthz/using-authz-api

https://learn.microsoft.com/en-us/windows/win32/secauthz/checking-access-with-authz-api

仅仅尝试访问有问题的文件是不够的。测试将在运行程序的用户的权限下运行——这并不一定是您想要测试的用户权限。