当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何检查写入目录或文件的权限?》经验,为你挑选了4个好方法。

我有一个程序,使用如下所示的方法将一些数据写入文件.

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 String msgPath,Boolean bFromProxy(字符串路径,FileMode模式,FileAccess访问FileShare共享,Int32 bufferSize,FileOptions选项,字符串msgPath,Boolea bFromProxy)

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



1> Josh..:

更新:

修改了基于此答案的代码,以摆脱过时的方法.

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

}

至于获得这些许可,您将不得不要求用户以某种方式为您执行此操作.如果您可以以编程方式执行此操作,那么我们都会遇到麻烦;)


此解决方案不起作用,即使我对该文件没有写入权限,SecurityManager.IsGranted也返回true(Win XP SP3)
SecurityManager.IsGranted归为Obsolete.这个答案可能不会永远有效.
@Jetnor - 您正在寻找[`SecurityManager.IsGranted`](http://msdn.microsoft.com/en-us/library/system.security.securitymanager.isgranted(v = vs.90).aspx)方法.它在4.0中被弃用,转而使用`PermissionSets`.上面的代码应该没有太大的不同,但不是检查"PermissionSet",而是一次只检查单个权限.
@Josh在你的电脑上尝试这个...创建一个新文件夹,(确保它有管理员,完全控制它,你是Administrators组的一部分),然后将你自己/ Windows帐户添加到安全列表,然后编辑您的权限并将Deny置于Write ...您的方法返回True for Write,因为Administrators具有Write访问权限,而Deny优先于您的帐户条目.因此,您的方法对我不起作用...请参阅下面的答案.

2> Iain..:

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

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

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

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

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

示例(源自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.
}

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


这种理念一切都很好,但并不普遍有效.例如,我需要显示一个对话框,用户选择我要写入的文件夹的路径,并且我想用一个合理的初始值作为建议填充对话框,如果它没有创建目标文件夹不存在.出于向后兼容性原因,该默认路径为"C:\ ".如果用户无法在那里写,我想回到AppData下的默认值.我无法尝试创建文件夹,然后再次删除它,只是为了确定文件夹浏览对话框的初始值.

3> xmen..:

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



4> 小智..:

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

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

推荐阅读
mobiledu2402851323
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有