[英]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
实例。
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 ?如何获得
group
和others
,或者……我对等价事物的定义?
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.此时有两种扩展方法:
GetAccessControl
和SetAccessControl
,分别用于FileInfo
、 DirectoryInfo
等。
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.请注意,
GetAccessControl
和SetAccessControl
在System.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.AccessControl
和System.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.