C # 사용자에게 폴더에 대한 쓰기 권한이 있는지 테스트
실제로 시도하기 전에 사용자가 폴더에 쓸 수 있는지 테스트해야합니다.
Directory.GetAccessControl () 메서드를 사용하여 폴더에 대한 보안 권한을 검색하려고 시도하는 다음 메서드 (C # 2.0)를 구현했습니다 .
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;
}
}
내가 쓰기 액세스를 테스트하는 방법을 인터넷 검색 할 때 이와 같은 것은 나타나지 않았으며 실제로 Windows에서 권한을 테스트하는 것은 매우 복잡해 보였습니다. 나는 지나치게 단순화하고 있으며이 방법이 효과가있는 것처럼 보이지만이 방법이 강력하지 않다는 것에 우려하고 있습니다.
현재 사용자에게 쓰기 액세스 권한이 있는지 테스트하는 방법이 올바르게 작동합니까?
이것이 C #에서 폴더 액세스를 확인하는 데 유효한 방법입니다. 예외 가 발생할 수있는 유일한 장소는 예외의 오버 헤드가 문제 가 될 수 있는 단단한 루프에서 이것을 호출 해야하는 경우 입니다.
이 게시물의 날짜가 약간 늦었지만 감사합니다.이 코드가 유용 할 수 있습니다.
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();
콘솔 앱에 드롭하고 필요한 작업인지 확인하십시오.
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;
}
}
나는 이것들의 대부분을 시도했지만 그것들은 같은 이유로 거짓 긍정을 준다. 사용 가능한 권한에 대해 디렉토리를 테스트하는 것만으로는 충분하지 않다. 허가. 이를 위해 사용자 ID를 확보하고 FileSystemAccessRule IdentityReference를 포함하는 그룹의 구성원인지 확인하십시오. 나는 이것을 테스트하고 완벽하게 작동합니다 ..
/// <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;
}
예를 들어 모든 사용자 (Builtin \ Users)에게이 방법은 잘 작동합니다.
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;
}
}
IMHO 디렉토리에 쓸 수 있는지 테스트하는 유일한 100 % 신뢰할 수있는 방법은 실제로 디렉토리에 쓰고 결국 예외를 포착하는 것입니다.
이 시도:
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");
}
코드는 DirectorySecurity주어진 디렉토리에 대한를 가져오고 (보안 정보에 액세스 할 수 없기 때문에) 예외를 올바르게 처리합니다. 그러나 샘플에서는 실제로 어떤 액세스가 허용되는지 확인하기 위해 반환 된 객체를 조사하지 않으며 이것을 추가해야한다고 생각합니다.
다음은 명시 적 거부 액세스 규칙을 설명하는 CsabaS의 답변 수정 버전입니다 . 이 함수는 디렉토리에 대한 모든 FileSystemAccessRules를 통과하고 현재 사용자가 디렉토리에 액세스 할 수있는 역할을 수행하는지 확인합니다. 이러한 역할을 찾을 수 없거나 사용자가 액세스가 거부 된 역할을하는 경우이 함수는 false를 반환합니다. 읽기 권한을 확인하려면 FileSystemRights.Read를 함수에 전달하십시오. 쓰기 권한을 얻으려면 FileSystemRights.Write를 전달하십시오. 현재 사용자가 아닌 임의의 사용자 권한을 확인하려면 currentUser WindowsIdentity를 원하는 WindowsIdentity로 대체하십시오. 또한 사용자가 디렉토리를 안전하게 사용할 수 있는지 확인하기 위해 이와 같은 기능에 의존하지 않는 것이 좋습니다. 이 답변은 이유를 완벽하게 설명합니다.
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;
}
파일에 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;
}
}
디렉토리에 쓰기 액세스 권한이 있는지 확인하기 위해 다음 코드 블록을 시도 할 수 있습니다. FileSystemAccessRule을 확인합니다.
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
}
코드에 잠재적 인 경쟁 조건이 있습니다. 확인시 폴더에 쓸 수있는 권한이 사용자에게 있지만 실제로 사용자가 폴더에 쓰기 전에이 권한이 철회됩니까? 쓰기는 예외를 처리하여 잡아서 처리해야합니다. 따라서 초기 점검은 의미가 없습니다. 쓰기 만하고 예외를 처리 할 수도 있습니다. 이것은 상황에 맞는 표준 패턴입니다.
http://www.codeproject.com/KB/files/UserFileAccessRights.aspx
매우 유용한 클래스, 다음 메시지에서 개선 된 버전을 확인하십시오.
위의 솔루션은 좋지만 나에게는이 코드가 간단하고 실행 가능하다는 것을 알았습니다. 임시 파일을 만드십시오. 파일이 작성되면 평균 사용자는 쓰기 액세스 권한을 갖습니다.
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;
}
문제의 파일에 접근하는 것만으로는 충분하지 않습니다. 테스트는 프로그램을 실행하는 사용자의 권한으로 실행됩니다. 반드시 테스트하려는 사용자 권한이 아닙니다.
Ash에 동의합니다. 괜찮습니다. 또는 선언적 CAS를 사용하여 실제로 프로그램에 액세스 할 수없는 경우 처음부터 프로그램이 실행되지 못하게 할 수 있습니다.
CAS 기능 중 일부는 내가 들었던 것에서 C # 4.0에 없을 수 있다고 생각합니다. 문제가 있는지 여부는 확실하지 않습니다.
허용 된 답변에서 권장하는대로 Windows 7에서 GetAccessControl ()이 예외를 throw하지 못했습니다.
나는 sdds의 답변을 변형하여 사용했습니다 .
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;
}
도움이 되었기를 바랍니다.
나는 같은 문제에 직면했다 : 특정 디렉토리에서 읽고 쓸 수 있는지 확인하는 방법. 나는 실제로 그것을 테스트하는 쉬운 해결책으로 끝났다. 여기에 간단하지만 효과적인 해결책이 있습니다.
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
}
그것이 도움이되기를 바랍니다!
참고 URL : https://stackoverflow.com/questions/1410127/c-sharp-test-if-user-has-write-access-to-a-folder
'Programming' 카테고리의 다른 글
| Objective-C Cocoa 애플리케이션의 정규 표현식 (0) | 2020.05.23 |
|---|---|
| 자바 배열 반영 : isArray와 instanceof (0) | 2020.05.23 |
| 표시와 반대되는 것이 있습니까? (0) | 2020.05.23 |
| Windows OS 용 OpenJDK 가용성 (0) | 2020.05.23 |
| JavaScript에서 문자열로 캐스트 (0) | 2020.05.23 |