如何在 .NET Core 中修改文件访问控制

Posted

技术标签:

【中文标题】如何在 .NET Core 中修改文件访问控制【英文标题】:How to modify file access control in .NET Core 【发布时间】:2017-03-19 21:34:30 【问题描述】:

我正在尝试更改 .NET Core 中文件的权限。 但是,FileInfo 似乎不再有任何SetAccessControl

// Create a new FileInfo object.
FileInfo fInfo = new FileInfo(FileName);

// Get a FileSecurity object that represents the 
// current security settings.
FileSecurity fSecurity = fInfo.GetAccessControl();

// Add the FileSystemAccessRule to the security settings. 
fSecurity.AddAccessRule(new FileSystemAccessRule(Account,
                                                Rights,
                                                ControlType));

// Set the new access settings.
fInfo.SetAccessControl(fSecurity);

目标只是为文件的当前所有者添加执行权(这不是 Windows 或 Unix 特定的功能)。

关于如何在 .NET Core 上执行此操作的任何线索?

【问题讨论】:

您希望在具有不同访问控制系统的 Unix 上发生什么?还是这是一个仅限 Windows 的 .Net Core 应用程序? @svick 我希望有一个共同的子集。我会检查 Mono 上做了什么(如果已经完成)。 【参考方案1】:

FileSecurity 类现在是 .NET Core 的 System.IO.FileSystem.AccessControl 包的一部分。不再有 File.GetAccessControl 方法,因此您需要自己实例化 FileSecurity 实例。

【讨论】:

顺便说一句,创建新的 .NET Core 2.0 库将不包含此程序集。您必须将 System.IO.FileSystem.AccessControl 添加为 NuGet 包。 @Scyssion 是的,我的评论是这样说的。 举个例子会有很大帮助。我在任何地方都找不到 .net 核心的工作示例。 @Learner 查看unit tests project in the Github repository 示例 请注意,与 .NET Core API 不同,该包不支持长文件名。有关详细信息,请在下面查看我的其他答案。【参考方案2】:

此时有两种扩展方式:GetAccessControlSetAccessControl,用于FileInfoDirectoryInfo

所以你可以使用var ac = new FileInfo(path).GetAccessControl(),这个表达式在 .NET Framework 和 .Net Core 中都有效。但是你仍然需要dotnet add package System.IO.FileSystem.AccessControl

File.GetAccessControl 在 .NET Core 中不可用。

参考:https://docs.microsoft.com/dotnet/api/system.io.filesystemaclextensions.getaccesscontrol

【讨论】:

应该是公认的答案,这样更容易使用【参考方案3】:

如何在 Windows 上获取和修改用户组其他权限

我终于实现了Windows文件权限访问:

1.获取文件安全性:

      var security = new FileSecurity(fileSystemInfoFullName, 
                AccessControlSections.Owner | 
                AccessControlSections.Group |
                AccessControlSections.Access);

2。获取授权规则:

var authorizationRules = security.GetAccessRules(true, true, typeof(NTAccount));

3.获取所有者的授权规则:

var owner = security.GetOwner(typeof(NTAccount));
foreach (AuthorizationRule rule in authorizationRules)

    FileSystemAccessRule fileRule = rule as FileSystemAccessRule;
    if (fileRule != null)
    
        if (owner != null && fileRule.IdentityReference == owner)
        
             if (fileRule.FileSystemRights.HasFlag(FileSystemRights.ExecuteFile) ||
                fileRule.FileSystemRights.HasFlag(FileSystemRights.ReadAndExecute) ||
                fileRule.FileSystemRights.HasFlag(FileSystemRights.FullControl))
            
                ownerRights.IsExecutable = true;
            
        
        else if (group != null && fileRule.IdentityReference == group)
        
            // TO BE CONTINUED...
        
    

4.为所有者添加规则:

security.ModifyAccessRule(AccessControlModification.Add,
    new FileSystemAccessRule(owner, FileSystemRights.Modify, AccessControlType.Allow),
    out bool modified);

5.奖金

如何获得groupothers,或者...我对等价物的定义?

var group = security.GetGroup(typeof(NTAccount));

var others = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null)
                 .Translate(typeof(NTAccount));

注意:此代码来自我的开源项目Lx.Shell

【讨论】:

这打击......他们为什么要让它变得如此复杂?为什么没有 DirectoryInfo 和 FileInfo 上的一些扩展方法? 这适用于 UNIX:***.com/questions/45132081/… 您的代码中的“ownerRights”和“group”是什么?【参考方案4】:

文档说这是受支持的并且它有效(对我来说)。 https://docs.microsoft.com/en-us/dotnet/api/system.io.filesystemaclextensions?view=dotnet-plat-ext-3.1 有一个 SetAccessControl 方法

请务必添加System.IO.FileSystem.AccessControl NuGet 包。

这是我在 .NET Framework 中的内容:

var ds = new DirectorySecurity();
ds.AddAccessRule(new FileSystemAccessRule(adminSI, FileSystemRights.FullControl, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow));
ds.SetAccessRuleProtection(true, false); // disable inheritance and clear any inherited permissions

Directory.SetAccessControl(<path to directory>, ds);

这就是它在 .NET Core 3.1 中的作用。只有最后一行不同:

var ds = new DirectorySecurity();
ds.AddAccessRule(new FileSystemAccessRule(adminSI, FileSystemRights.FullControl, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow));
ds.SetAccessRuleProtection(true, false); // disable inheritance and clear any inherited permissions

System.IO.FileSystemAclExtensions.SetAccessControl(new DirectoryInfo(<path to directory>), ds);

【讨论】:

【参考方案5】:

这是为了补充其他答案。请注意,System.IO.FileSystem.AccessControl 中的 GetAccessControlSetAccessControl 与其他 .NET Core System.IO API 一样支持长文件名(255 个字符)。

你收到的异常是内部调用抛出的ArgumentException,参数是name

如果你使用的是那个包,如果你发现长文件名,你需要添加这个:

if (usingFile.FullName.Length > 255)

    usingFile = new FileInfo(@"\\?\" + file.FullName);

if (folder.FullName.Length > 255)

    folder = new DirectoryInfo(@"\\?\" + folder.FullName);

【讨论】:

【参考方案6】:

另一种处理目录或文件的acls的方法:

       // Adds an ACL entry on the specified directory for the specified account.
    public static void AddDirectorySecurity(string FileName, string Account, FileSystemRights Rights, AccessControlType ControlType)
    
        // Create a new DirectoryInfo object.
        DirectoryInfo dInfo = new DirectoryInfo(FileName);

        // Get a DirectorySecurity object that represents the 
        // current security settings.
        DirectorySecurity dSecurity = dInfo.GetAccessControl();

        // Add the FileSystemAccessRule to the security settings. 
        dSecurity.AddAccessRule(new FileSystemAccessRule(Account,
                                                        Rights,
                                                        ControlType));

        // Set the new access settings.
        dInfo.SetAccessControl(dSecurity);
    

    // Removes an ACL entry on the specified directory for the specified account.
    public static void RemoveDirectorySecurity(string FileName, string Account, FileSystemRights Rights, AccessControlType ControlType)
    
        // Create a new DirectoryInfo object.
        DirectoryInfo dInfo = new DirectoryInfo(FileName);

        // Get a DirectorySecurity object that represents the 
        // current security settings.
        DirectorySecurity dSecurity = dInfo.GetAccessControl();

        // Add the FileSystemAccessRule to the security settings. 
        dSecurity.RemoveAccessRule(new FileSystemAccessRule(Account,
                                                        Rights,
                                                        ControlType));

        // Set the new access settings.
        dInfo.SetAccessControl(dSecurity);
    

    // Adds an ACL entry on the specified file for the specified account.
    public static void AddFileSecurity(string fileName, string account,
        FileSystemRights rights, AccessControlType controlType)
    

        // Create a new FileInfo object.
        FileInfo fInfo = new FileInfo(fileName);

        // Get a FileSecurity object that represents the 
        // current security settings.
        FileSecurity fSecurity = fInfo.GetAccessControl();

        // Add the FileSystemAccessRule to the security settings.
        fSecurity.AddAccessRule(new FileSystemAccessRule(account,
            rights, controlType));

        // Set the new access settings.
        fInfo.SetAccessControl(fSecurity);
    

    // Removes an ACL entry on the specified file for the specified account.
    public static void RemoveFileSecurity(string fileName, string account,
        FileSystemRights rights, AccessControlType controlType)
    

        // Create a new FileInfo object.
        FileInfo fInfo = new FileInfo(fileName);

        // Get a FileSecurity object that represents the 
        // current security settings.
        FileSecurity fSecurity = fInfo.GetAccessControl();

        // Remove the FileSystemAccessRule from the security settings.
        fSecurity.RemoveAccessRule(new FileSystemAccessRule(account,
            rights, controlType));

        // Set the new access settings.
        fInfo.SetAccessControl(fSecurity);
    

    //example for open onClick folderdialog and get owner by NTACCOUNT of folder from acl
    private async void Button_Click(object sender, RoutedEventArgs e)
    
        var folderPicker = new Windows.Storage.Pickers.FolderPicker();
        folderPicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.Desktop;
        folderPicker.FileTypeFilter.Add("*");

        Windows.Storage.StorageFolder folder = await folderPicker.PickSingleFolderAsync();
        if (folder != null)
        
            // Application now has read/write access to all contents in the picked folder
            // (including other sub-folder contents)
            Windows.Storage.AccessCache.StorageApplicationPermissions.
            FutureAccessList.AddOrReplace("PickedFolderToken", folder);

            // Create a new FileInfo object.
            FileInfo fInfo = new FileInfo(folder.ToString());

            // Get a FileSecurity object that represents the 
            // current security settings.
            FileSecurity fSecurity = fInfo.GetAccessControl();

            IdentityReference identityReference = fSecurity.GetOwner(typeof(SecurityIdentifier));
            NTAccount ntAccount = identityReference.Translate(typeof(NTAccount)) as NTAccount;
            var fileOwner = ntAccount.Value;


            //do something with file Owner
            //this.tb1.Text = "folder: " + folder.Name + " in Pfad: " + folder.Path + "owned by: " + fileOwner;
        
        else
        
            //error Handler
        

    

【讨论】:

正如原来的问题所说...... Net Core 不再有 GetAccessControl 或 SetAccessControl 方法在 DirectoryInfo 上 GetAccessControl 和 SetAccessControl 已完全从 Net Core 3.0 及更高版本中撤出,但它可以在 2.2 中使用。如果你试图运行它,你会得到一个 Method Not Found 异常(或类似的东西)。我有一个正是这个问题的多目标项目,它适用于 Framework 4.7.2 和 Core 2.2,但在 Core 3.0 和 3.1 上失败。 然后它来自 2.2。项目。谢谢

以上是关于如何在 .NET Core 中修改文件访问控制的主要内容,如果未能解决你的问题,请参考以下文章

如何让asp.net core mvc发布时候不编译cshtml视图

如何使用 Asp.Net Core 实现基于权限的访问控制

修改 ASP .NET Core 中的登录页面文本

ASP.NET Core 访问控制器构造函数中的 User.Identity

使用.net core读取Json文件配置

如何在ASP.NET Core中编写高效的控制器