简体   繁体   English

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

[英]How to modify file access control in .NET Core

I'm trying to change the permissions of a file in .NET Core.我正在尝试更改 .NET Core 中文件的权限。 However, it seems that FileInfo doesn't have any SetAccessControl anymore.但是,似乎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);

The goal is just to add execution right to the current owner of a file (which is not Windows or Unix specific feature).目标只是为文件的当前所有者添加执行权(这不是 Windows 或 Unix 特定功能)。

Any clues on how to do that on .NET Core?关于如何在 .NET Core 上执行此操作的任何线索?

The FileSecurity class is now part of the System.IO.FileSystem.AccessControl package for .NET Core. FileSecurity类现在是 .NET Core 的System.IO.FileSystem.AccessControl包的一部分。 There is no longer a File.GetAccessControl method so you will need to instantiate the FileSecurity instance yourself.不再有File.GetAccessControl方法,因此您需要自己实例化FileSecurity实例。

How to Get and modify User Group Other Rights on Windows如何在 Windows 上获取和修改用户组其他权限

I finally implement the Windows file permission access:我终于实现了Windows文件权限访问:

1. Get the file security: 1.获取文件安全:

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

2. Get the authorization rules: 2、获取授权规则:

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

3. Get the authorization rules for the owner: 3.获取owner的授权规则:

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. Add a rule for owner: 4. 为所有者添加规则:

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

5. Bonus 5. 奖金

How to get the group and others , or ... my definition of something equivalent ?如何获得groupothers ,或者……我对​​等价事物的定义?

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

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

Note: This code comes from my open source project Lx.Shell注意:此代码来自我的开源项目Lx.Shell

At this time there are two extension methods: GetAccessControl and SetAccessControl , for FileInfo , DirectoryInfo and etc.此时有两种扩展方法: GetAccessControlSetAccessControl ,分别用于FileInfoDirectoryInfo等。

So you can use var ac = new FileInfo(path).GetAccessControl() , this expression is valid both in .NET Framework and .Net Core.所以你可以使用var ac = new FileInfo(path).GetAccessControl() ,这个表达式在 .NET Framework 和 .Net Core 中都有效。 But you still need dotnet add package System.IO.FileSystem.AccessControl .但是您仍然需要dotnet add package System.IO.FileSystem.AccessControl

File.GetAccessControl isn't available in .NET Core. File.GetAccessControl在 .NET Core 中不可用。

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

The documentation says this IS supported and it works (for me).文档说这是支持的并且它有效(对我来说)。 https://docs.microsoft.com/en-us/dotnet/api/system.io.filesystemaclextensions?view=dotnet-plat-ext-3.1 DOES have a SetAccessControl method https://docs.microsoft.com/en-us/dotnet/api/system.io.filesystemaclextensions?view=dotnet-plat-ext-3.1确实有 SetAccessControl 方法

Be sure to add the System.IO.FileSystem.AccessControl NuGet package.请务必添加System.IO.FileSystem.AccessControl NuGet 包。

Here's what I had in .NET Framework:这是我在 .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);

And here's what it is working in .NET Core 3.1.这就是它在 .NET Core 3.1 中的作用。 Only the last line is different:只有最后一行不同:

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

This is to add to other answers.这是添加到其他答案。 Note that the GetAccessControl and SetAccessControl in the System.IO.FileSystem.AccessControl does NOT support long file name (255 chars) like other .NET Core System.IO APIs.请注意, GetAccessControlSetAccessControlSystem.IO.FileSystem.AccessControl支持长文件名(255个字符)像其他.NET核心System.IO的API。

The exception you receive is ArgumentException thrown by internal calls, the parameter is name .您收到的异常是内部调用抛出的ArgumentException ,参数是name

If you are using that package, you need to add this if you may find long file name:如果您正在使用该软件包,如果您发现长文件名,则需要添加以下内容:

if (usingFile.FullName.Length > 255)
{
    usingFile = new FileInfo(@"\\?\" + file.FullName);
}

or

if (folder.FullName.Length > 255)
{
    folder = new DirectoryInfo(@"\\?\" + folder.FullName);
}

Another way to handle acls for directory or file:处理目录或文件的 acl 的另一种方法:

       // 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
        }

    }

Following what @jon-r said, I was able to get mine working.按照@jon-r 所说的,我能够让我的工作正常进行。 This is still relevant in .NET 7. This is using System.IO.FileSystem.AccessControl and System.IO NuGet packages.这在 .NET 7 中仍然相关。这是使用System.IO.FileSystem.AccessControlSystem.IO NuGet 包。

My .NET Framework 4.8 code:我的 .NET Framework 4.8 代码:

var ds = Directory.GetAccessControl(dir);
ds.AddAccessRule(new FileSystemAccessRule(user, FileSystemRights.Modify, InheritanceFlags.ContainerInherit, PropagationFlags.None, AccessControlType.Allow));
ds.AddAccessRule(new FileSystemAccessRule(user, FileSystemRights.Modify, InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow));
Directory.SetAccessControl(dir, ds);

My .NET 7 code:我的 .NET 7 代码:

var ds = new DirectorySecurity();
ds.AddAccessRule(new FileSystemAccessRule(user, FileSystemRights.FullControl, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow));
System.IO.FileSystemAclExtensions.SetAccessControl(new DirectoryInfo(dir), ds);

My initial code looked a little different than Jon's so I wanted to include it for others.我的初始代码看起来与 Jon 的略有不同,所以我想将它包含在其他人手中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM