Как изменить контроль доступа к файлам в.NET Core
Я пытаюсь изменить права доступа к файлу в.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?
7 ответов
FileSecurity
теперь класс является частью пакета https://www.nuget.org/packages/System.IO.FileSystem.AccessControl/ для.NET Core. Там больше нет File.GetAccessControl
метод, так что вам нужно будет создать экземпляр FileSecurity
пример себя.
На данный момент существует два метода расширения: GetAccessControl
а также SetAccessControl
, за FileInfo
, DirectoryInfo
и так далее.
Итак, вы можете использовать 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
Как получить и изменить группу пользователей Другие права в 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. Бонус
Как получить group
а также others
или... мое определение чего-то эквивалентного?
var group = security.GetGroup(typeof(NTAccount));
var others = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null)
.Translate(typeof(NTAccount));
Примечание. Этот код взят из моего проекта с открытым исходным кодом Lx.Shell.
В документации говорится, что эта IS поддерживается, и она работает (для меня). 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);
После того, что сказал @jon-r, я смог заставить свою работать. Это по-прежнему актуально в .NET 7. Здесь используетсяSystem.IO.FileSystem.AccessControl
иSystem.IO
NuGet-пакеты.
Мой код .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);
Мой код .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);
Мой первоначальный код выглядел немного иначе, чем у Джона, поэтому я хотел включить его для других.
Это добавить к другим ответам. Обратите внимание, чтоGetAccessControl
а также SetAccessControl
в System.IO.FileSystem.AccessControl
это НЕ поддерживает длинные имена файлов (255 символов), как и другие.NET ЯдраSystem.IO
API.
Вы получаете исключение ArgumentException
вызывается внутренними вызовами, параметр name
.
Если вы используете этот пакет, вам нужно добавить это, если вы можете найти длинное имя файла:
if (usingFile.FullName.Length > 255)
{
usingFile = new FileInfo(@"\\?\" + file.FullName);
}
или
if (folder.FullName.Length > 255)
{
folder = new DirectoryInfo(@"\\?\" + folder.FullName);
}
Другой способ обработки 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
}
}