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

我已经实现了以下方法(在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中测试权限看起来非常复杂。我担心我过于简化了事情,这个方法并不健壮,尽管它似乎确实有效。

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


当前回答

我无法让GetAccessControl()在Windows 7上抛出一个异常,就像接受的答案中建议的那样。

我最终使用了sdds的答案的变体:

        try
        {
            bool writeable = false;
            WindowsPrincipal principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
            DirectorySecurity security = Directory.GetAccessControl(pstrPath);
            AuthorizationRuleCollection authRules = security.GetAccessRules(true, true, typeof(SecurityIdentifier));

            foreach (FileSystemAccessRule accessRule in authRules)
            {

                if (principal.IsInRole(accessRule.IdentityReference as SecurityIdentifier))
                {
                    if ((FileSystemRights.WriteData & accessRule.FileSystemRights) == FileSystemRights.WriteData)
                    {
                        if (accessRule.AccessControlType == AccessControlType.Allow)
                        {
                            writeable = true;
                        }
                        else if (accessRule.AccessControlType == AccessControlType.Deny)
                        {
                            //Deny usually overrides any Allow
                            return false;
                        }

                    } 
                }
            }
            return writeable;
        }
        catch (UnauthorizedAccessException)
        {
            return false;
        }

希望这能有所帮助。

其他回答

http://www.codeproject.com/KB/files/UserFileAccessRights.aspx

非常有用的类,检查以下消息的改进版本。

Here is a modified version of CsabaS's answer, which accounts for explicit deny access rules. The function goes through all FileSystemAccessRules for a directory, and checks if the current user is in a role which has access to a directory. If no such roles are found or the user is in a role with denied access, the function returns false. To check read rights, pass FileSystemRights.Read to the function; for write rights, pass FileSystemRights.Write. If you want to check an arbitrary user's rights and not the current one's, substitute the currentUser WindowsIdentity for the desired WindowsIdentity. I would also advise against relying on functions like this to determine if the user can safely use the directory. This answer perfectly explains why.

    public static bool UserHasDirectoryAccessRights(string path, FileSystemRights accessRights)
    {
        var isInRoleWithAccess = false;

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

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

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

                    if (principal.IsInRole(ntAccount.Value))
                    {
                        if (fsAccessRule.AccessControlType == AccessControlType.Deny)
                            return false;
                        isInRoleWithAccess = true;
                    }
                }
            }
        }
        catch (UnauthorizedAccessException)
        {
            return false;
        }
        return isInRoleWithAccess;
    }

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

您可以尝试以下代码块来检查目录是否具有写访问权限。 它检查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 
}

您的代码获得给定目录的DirectorySecurity,并正确处理异常(由于您无法访问安全性信息)。然而,在您的示例中,您实际上并没有询问返回的对象以查看允许哪些访问—我认为您需要添加这一点。