C# Test czy użytkownik ma prawo zapisu do folderu
Muszę sprawdzić, czy użytkownik może zapisać do folderu, zanim faktycznie spróbuje to zrobić.
Zaimplementowałem następującą metodę (w C# 2.0), która próbuje odzyskać uprawnienia zabezpieczeń dla folderu używając katalogu .Metoda GetAccessControl () .
private bool hasWriteAccessToFolder(string folderPath)
{
try
{
// Attempt to get a list of security permissions from the folder.
// This will raise an exception if the path is read only or do not have access to view the permissions.
System.Security.AccessControl.DirectorySecurity ds = Directory.GetAccessControl(folderPath);
return true;
}
catch (UnauthorizedAccessException)
{
return false;
}
}
Kiedy googlowałem, Jak testować dostęp do zapisu, nic takiego nie wyskoczyło i okazało się bardzo skomplikowane testowanie uprawnień w systemie Windows. Obawiam się, że przesadzam z upraszczaniem i że ta metoda nie jest solidna, chociaż wydaje się działać.
Czy moja metoda sprawdzania, czy bieżący użytkownik ma dostęp do zapisu działa poprawnie?
18 answers
To doskonały sposób na sprawdzenie dostępu do folderów w C#. Jedynym miejscem, w którym może spaść, jest wywołanie tego w ciasnej pętli, gdzie narzut wyjątku może być problemem.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:33
Doceniam to, że jest to trochę za późno na ten post, ale może uznasz ten kawałek kodu za przydatny.
string path = @"c:\temp";
string NtAccountName = @"MyDomain\MyUserOrGroup";
DirectoryInfo di = new DirectoryInfo(path);
DirectorySecurity acl = di.GetAccessControl(AccessControlSections.All);
AuthorizationRuleCollection rules = acl.GetAccessRules(true, true, typeof(NTAccount));
//Go through the rules returned from the DirectorySecurity
foreach (AuthorizationRule rule in rules)
{
//If we find one that matches the identity we are looking for
if (rule.IdentityReference.Value.Equals(NtAccountName,StringComparison.CurrentCultureIgnoreCase))
{
var filesystemAccessRule = (FileSystemAccessRule)rule;
//Cast to a FileSystemAccessRule to check for access rights
if ((filesystemAccessRule.FileSystemRights & FileSystemRights.WriteData)>0 && filesystemAccessRule.AccessControlType != AccessControlType.Deny)
{
Console.WriteLine(string.Format("{0} has write access to {1}", NtAccountName, path));
}
else
{
Console.WriteLine(string.Format("{0} does not have write access to {1}", NtAccountName, path));
}
}
}
Console.ReadLine();
Wrzuć to do aplikacji konsoli i sprawdź, czy robi to, czego potrzebujesz.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-02 12:12:55
public bool IsDirectoryWritable(string dirPath, bool throwIfFails = false)
{
try
{
using (FileStream fs = File.Create(
Path.Combine(
dirPath,
Path.GetRandomFileName()
),
1,
FileOptions.DeleteOnClose)
)
{ }
return true;
}
catch
{
if (throwIfFails)
throw;
else
return false;
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-17 18:27:01
Próbowałem większości z nich, ale dają fałszywe wyniki, wszystkie z tego samego powodu.. Nie wystarczy przetestować katalog pod kątem dostępnych uprawnień, trzeba sprawdzić, czy zalogowany użytkownik jest członkiem grupy, która ma takie uprawnienia. Aby to zrobić, można uzyskać tożsamość użytkownika i sprawdzić, czy jest członkiem grupy, która zawiera Filesystememaccessrule IdentityReference. Przetestowałem to, działa bez zarzutu..
/// <summary>
/// Test a directory for create file access permissions
/// </summary>
/// <param name="DirectoryPath">Full path to directory </param>
/// <param name="AccessRight">File System right tested</param>
/// <returns>State [bool]</returns>
public static bool DirectoryHasPermission(string DirectoryPath, FileSystemRights AccessRight)
{
if (string.IsNullOrEmpty(DirectoryPath)) return false;
try
{
AuthorizationRuleCollection rules = Directory.GetAccessControl(DirectoryPath).GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));
WindowsIdentity identity = WindowsIdentity.GetCurrent();
foreach (FileSystemAccessRule rule in rules)
{
if (identity.Groups.Contains(rule.IdentityReference))
{
if ((AccessRight & rule.FileSystemRights) == AccessRight)
{
if (rule.AccessControlType == AccessControlType.Allow)
return true;
}
}
}
}
catch { }
return false;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-24 19:00:15
Na przykład dla wszystkich użytkowników (Builtin\Users), ta metoda działa dobrze-enjoy.
public static bool HasFolderWritePermission(string destDir)
{
if(string.IsNullOrEmpty(destDir) || !Directory.Exists(destDir)) return false;
try
{
DirectorySecurity security = Directory.GetAccessControl(destDir);
SecurityIdentifier users = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
foreach(AuthorizationRule rule in security.GetAccessRules(true, true, typeof(SecurityIdentifier)))
{
if(rule.IdentityReference == users)
{
FileSystemAccessRule rights = ((FileSystemAccessRule)rule);
if(rights.AccessControlType == AccessControlType.Allow)
{
if(rights.FileSystemRights == (rights.FileSystemRights | FileSystemRights.Modify)) return true;
}
}
}
return false;
}
catch
{
return false;
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-22 13:50:33
IMHO jedynym w 100% wiarygodnym sposobem na sprawdzenie, czy można pisać do katalogu, jest rzeczywiście pisać do niego i ostatecznie łapać wyjątki.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-11 10:16:48
Spróbuj tego:
try
{
DirectoryInfo di = new DirectoryInfo(path);
DirectorySecurity acl = di.GetAccessControl();
AuthorizationRuleCollection rules = acl.GetAccessRules(true, true, typeof(NTAccount));
WindowsIdentity currentUser = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(currentUser);
foreach (AuthorizationRule rule in rules)
{
FileSystemAccessRule fsAccessRule = rule as FileSystemAccessRule;
if (fsAccessRule == null)
continue;
if ((fsAccessRule.FileSystemRights & FileSystemRights.WriteData) > 0)
{
NTAccount ntAccount = rule.IdentityReference as NTAccount;
if (ntAccount == null)
{
continue;
}
if (principal.IsInRole(ntAccount.Value))
{
Console.WriteLine("Current user is in role of {0}, has write access", ntAccount.Value);
continue;
}
Console.WriteLine("Current user is not in role of {0}, does not have write access", ntAccount.Value);
}
}
}
catch (UnauthorizedAccessException)
{
Console.WriteLine("does not have write access");
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-19 13:04:58
Twój kod pobiera DirectorySecurity
dla danego katalogu i prawidłowo obsługuje wyjątek (z powodu braku dostępu do informacji o zabezpieczeniach). Jednak w Twojej próbce nie przesłuchujesz zwracanego obiektu, aby zobaczyć, jaki dostęp jest dozwolony - i myślę, że musisz to dodać.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-11 10:23:27
Użyłem tej samej funkcji do sprawdzenia, czy plik ma writeaccess:
private static bool HasWriteAccessToFile(string filePath)
{
try
{
// Attempt to get a list of security permissions from the file.
// This will raise an exception if the path is read only or do not have access to view the permissions.
File.GetAccessControl(filePath);
return true;
}
catch (UnauthorizedAccessException)
{
return false;
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-10 05:18:40
Oto zmodyfikowana wersja Odpowiedzi Csabasa , która odpowiada za wyraźne reguły odmowy dostępu. Funkcja Przechodzi przez wszystkie zasady Filesystememaccessrules dla katalogu i sprawdza, czy bieżący użytkownik jest w roli, która ma dostęp do katalogu. Jeśli nie znaleziono takich ról lub użytkownik jest w roli z odmową dostępu, funkcja zwraca false. Aby sprawdzić prawa do odczytu, podaj FileSystemRights.Odczyt do funkcji; dla praw zapisu podaj FileSystemRights.Pisz. Jeśli chcesz sprawdzić dowolne prawa użytkownika, a nie bieżące, zastąp bieżący WindowsIdentity użytkownika żądanym WindowsIdentity. Odradzam również poleganie na takich funkcjach w celu ustalenia, czy użytkownik może bezpiecznie korzystać z katalogu. Ta odpowiedź doskonale wyjaśnia dlaczego.
public static bool UserHasDirectoryAccessRights(string path, FileSystemRights accessRights)
{
var isInRoleWithAccess = false;
try
{
var di = new DirectoryInfo(path);
var acl = di.GetAccessControl();
var rules = acl.GetAccessRules(true, true, typeof(NTAccount));
var currentUser = WindowsIdentity.GetCurrent();
var principal = new WindowsPrincipal(currentUser);
foreach (AuthorizationRule rule in rules)
{
var fsAccessRule = rule as FileSystemAccessRule;
if (fsAccessRule == null)
continue;
if ((fsAccessRule.FileSystemRights & accessRights) > 0)
{
var ntAccount = rule.IdentityReference as NTAccount;
if (ntAccount == null)
continue;
if (principal.IsInRole(ntAccount.Value))
{
if (fsAccessRule.AccessControlType == AccessControlType.Deny)
return false;
isInRoleWithAccess = true;
}
}
}
}
catch (UnauthorizedAccessException)
{
return false;
}
return isInRoleWithAccess;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:17:58
Możesz spróbować podążać za blokiem kodu, aby sprawdzić, czy katalog ma dostęp do zapisu. Sprawdza system plików Accessrule.
string directoryPath = "C:\\XYZ"; //folderBrowserDialog.SelectedPath;
bool isWriteAccess = false;
try
{
AuthorizationRuleCollection collection =
Directory.GetAccessControl(directoryPath)
.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));
foreach (FileSystemAccessRule rule in collection)
{
if (rule.AccessControlType == AccessControlType.Allow)
{
isWriteAccess = true;
break;
}
}
}
catch (UnauthorizedAccessException ex)
{
isWriteAccess = false;
}
catch (Exception ex)
{
isWriteAccess = false;
}
if (!isWriteAccess)
{
//handle notifications
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-25 16:06:39
Masz potencjalny stan rasy w kodzie--co się stanie, jeśli użytkownik ma uprawnienia do zapisu do folderu po sprawdzeniu, ale zanim użytkownik faktycznie zapisze do folderu to uprawnienie zostanie wycofane? Zapis rzuci wyjątek, który będziesz musiał złapać i obsłużyć. Więc wstępna kontrola jest bezcelowa. Równie dobrze możesz po prostu napisać i obsłużyć wszelkie wyjątki. To jest standardowy wzór dla twojej sytuacji.
Http://www.codeproject.com/KB/files/UserFileAccessRights.aspx
Bardzo przydatna Klasa, sprawdź poprawną wersję w wiadomościach poniżej.
Po prostu próba uzyskania dostępu do danego pliku nie musi być wystarczająca. Test będzie uruchamiany z uprawnieniami użytkownika uruchamiającego program - które niekoniecznie są uprawnieniami użytkownika, z którymi chcesz testować.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-17 10:12:29
Powyższe rozwiązania są dobre, ale dla mnie ten kod jest prosty i wykonalny. Wystarczy utworzyć plik tymczasowy. Jeśli plik zostanie utworzony, jego użytkownik mean ma prawo zapisu.
public static bool HasWritePermission(string tempfilepath)
{
try
{
System.IO.File.Create(tempfilepath + "temp.txt").Close();
System.IO.File.Delete(tempfilepath + "temp.txt");
}
catch (System.UnauthorizedAccessException ex)
{
return false;
}
return true;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-25 08:00:29
Zgadzam się z Ashem, powinno być dobrze. Alternatywnie można użyć deklaratywnego CAS i faktycznie uniemożliwić uruchomienie programu w pierwszej kolejności, jeśli nie mają dostępu.
Uważam, że niektóre funkcje CAS mogą nie być obecne w C# 4.0 z tego co słyszałem, Nie wiem czy to może być problem czy nie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-11 10:21:55
Nie mogłem uzyskać GetAccessControl (), aby rzucić wyjątek w systemie Windows 7 zgodnie z zaleceniami w zaakceptowanej odpowiedzi.
W końcu użyłem wariantu sdds ' S odpowiedź:
try
{
bool writeable = false;
WindowsPrincipal principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
DirectorySecurity security = Directory.GetAccessControl(pstrPath);
AuthorizationRuleCollection authRules = security.GetAccessRules(true, true, typeof(SecurityIdentifier));
foreach (FileSystemAccessRule accessRule in authRules)
{
if (principal.IsInRole(accessRule.IdentityReference as SecurityIdentifier))
{
if ((FileSystemRights.WriteData & accessRule.FileSystemRights) == FileSystemRights.WriteData)
{
if (accessRule.AccessControlType == AccessControlType.Allow)
{
writeable = true;
}
else if (accessRule.AccessControlType == AccessControlType.Deny)
{
//Deny usually overrides any Allow
return false;
}
}
}
}
return writeable;
}
catch (UnauthorizedAccessException)
{
return false;
}
Mam nadzieję, że to pomoże.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:36
Napotkałem ten sam problem: jak sprawdzić, czy mogę odczytywać/zapisywać w danym katalogu. Skończyłem z łatwym rozwiązaniem...właściwie to przetestuj. Oto moje proste, choć skuteczne rozwiązanie.
class Program
{
/// <summary>
/// Tests if can read files and if any are present
/// </summary>
/// <param name="dirPath"></param>
/// <returns></returns>
private genericResponse check_canRead(string dirPath)
{
try
{
IEnumerable<string> files = Directory.EnumerateFiles(dirPath);
if (files.Count().Equals(0))
return new genericResponse() { status = true, idMsg = genericResponseType.NothingToRead };
return new genericResponse() { status = true, idMsg = genericResponseType.OK };
}
catch (DirectoryNotFoundException ex)
{
return new genericResponse() { status = false, idMsg = genericResponseType.ItemNotFound };
}
catch (UnauthorizedAccessException ex)
{
return new genericResponse() { status = false, idMsg = genericResponseType.CannotRead };
}
}
/// <summary>
/// Tests if can wirte both files or Directory
/// </summary>
/// <param name="dirPath"></param>
/// <returns></returns>
private genericResponse check_canWrite(string dirPath)
{
try
{
string testDir = "__TESTDIR__";
Directory.CreateDirectory(string.Join("/", dirPath, testDir));
Directory.Delete(string.Join("/", dirPath, testDir));
string testFile = "__TESTFILE__.txt";
try
{
TextWriter tw = new StreamWriter(string.Join("/", dirPath, testFile), false);
tw.WriteLine(testFile);
tw.Close();
File.Delete(string.Join("/", dirPath, testFile));
return new genericResponse() { status = true, idMsg = genericResponseType.OK };
}
catch (UnauthorizedAccessException ex)
{
return new genericResponse() { status = false, idMsg = genericResponseType.CannotWriteFile };
}
}
catch (UnauthorizedAccessException ex)
{
return new genericResponse() { status = false, idMsg = genericResponseType.CannotWriteDir };
}
}
}
public class genericResponse
{
public bool status { get; set; }
public genericResponseType idMsg { get; set; }
public string msg { get; set; }
}
public enum genericResponseType
{
NothingToRead = 1,
OK = 0,
CannotRead = -1,
CannotWriteDir = -2,
CannotWriteFile = -3,
ItemNotFound = -4
}
Mam nadzieję, że to pomoże !Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-08 14:39:25