【问题标题】:C# Linq for files user has read access toC# Linq for files 用户具有读取权限
【发布时间】:2011-11-22 11:18:10
【问题描述】:

如何在list.Items = directoryInfo.GetFiles("\\server\share\folder\"); 上使用 Linq 以仅包含用户具有读取权限的文件?

... 到目前为止,只有使用 try/catch 或 .NET 4.0 中已过时的 API 的建议?我更喜欢阅读 ACL 并查看特定用户或用户所属的组是否已被授予读取访问权限。我试图这样做是为了简化向流量不大的网站上向用户授予报告的管理,所以“谁知道你在尝试打开文件时是否可以真正阅读它”的逻辑并不与本案有关。我觉得微软真的应该让这项任务变得更容易。

【问题讨论】:

    标签: c# linq file-permissions acl


    【解决方案1】:

    注意:我还没有测试过,但理论上它应该可以工作

    首先,定义一个谓词来确定读访问权限

    bool CanRead(FileInfo file)
    {
      try {
        file.GetAccessControl();
        //Read and write access;
        return true;
      }
      catch (UnauthorizedAccessException uae)
      {
        if (uae.Message.Contains("read-only"))
        {
          //read-only access
          return true;
        }
        return false;
      }
    }
    


    然后,应该是在 linq 查询中使用 where 子句的简单案例
    from file in directoryInfo.GetFiles("\\server\share\folder\") 
      where HaveAccess(f) == true
        select f;
    

    【讨论】:

      【解决方案2】:

      试试这个吧。应该可以工作。虽然没有测试过

        var fw = from f in new DirectoryInfo("C:\\Users\\User\\Downloads\\").GetFiles()
                      where SecurityManager.IsGranted(new FileIOPermission
       (FileIOPermissionAccess.Write, f.FullName))
                      select f;
      

      编辑如果它只是只读文件然后试试这个

      var fe = from f in new DirectoryInfo("C:\\Users\\ashley\\Downloads\\").GetFiles()
                      where f.IsReadOnly==true
                      select f
      

      【讨论】:

      • 是的 ..但是在 catch 中说明一些逻辑听起来并不优雅。想象一下你有成千上万的文件并且等待异常发生以获取其状态是相当昂贵的操作..
      • @Ashley:我很确定那些 try/catch 是特殊情况(驱动器不存在,或者您完全被锁定在文件夹之外)。您可以从 Linq 查询中调用该函数,因此您的更高级别的代码仍然可以很漂亮。它已经封装了真/假,因此您只需将其插入where 子句。我不知道不使用 p/Invoke 是否有更好的选择(例如 Try 变体)。另外我认为枚举文件系统上的文件可能已经是一个瓶颈。我推测到那时异常将可以忽略不计。
      【解决方案3】:

      如果您在打开文件之前检查读取权限,您将面临竞争条件的风险。

      如果您尝试读取文件夹中您有权访问的所有文件,最好尝试打开每个文件并捕获UnauthorizedAccessException

      见:

      【讨论】:

        【解决方案4】:

        已经过测试并且可以工作,但是如果文件正在使用中会返回 false

        void Main()
        {
            var directoryInfo = new DirectoryInfo(@"C:\");
            var currentUser = WindowsIdentity.GetCurrent();
            var files = directoryInfo.GetFiles(".").Where(f => CanRead(currentUser, f.FullName));
        }
        
        private bool CanRead(WindowsIdentity user, string filePath)
        {
            if(!File.Exists(filePath))
                return false;
        
            try
            {
                var fileSecurity = File.GetAccessControl(filePath, AccessControlSections.Access); 
                foreach(FileSystemAccessRule fsRule in fileSecurity.GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier)))
                {
                    foreach(var usrGroup in user.Groups)
                    {
                        if(fsRule.IdentityReference.Value == usrGroup.Value)
                            return true;
                    }
                }
            } catch (InvalidOperationException) {
                //File is in use
                return false;
            }
        
            return false;
        }
        

        【讨论】:

        • 这适用于组内的组吗?显式拒绝权限怎么样?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-07
        • 2016-06-02
        • 2016-04-23
        • 2012-06-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多