디렉토리 나 파일에 쓸 수있는 권한을 어떻게 확인합니까?
아래와 같은 방법을 사용하여 파일에 일부 데이터를 쓰는 프로그램이 있습니다.
public void ExportToFile(string filename)
{
using(FileStream fstream = new FileStream(filename,FileMode.Create))
using (TextWriter writer = new StreamWriter(fstream))
{
// try catch block for write permissions
writer.WriteLine(text);
}
}
프로그램을 실행할 때 오류가 발생합니다.
처리되지 않은 예외 : System.UnauthorizedAccessException : 'mypath'경로에 대한 액세스가 거부되었습니다. System.IO .__ Error.WinIOError (Int32 errorCode, String maybeFullPath) at System.IO.FileStream.Init (String path, FileMode mode, FileAccess access, nt32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions ptions, SECURITY_ATTRIBUTES secAttrs , String msgPath, Boolean bFromProxy) at System.IO.FileStream..ctor (String path, FileMode mode, FileAccess access FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolea bFromProxy)
질문 :이를 포착하려면 어떤 코드가 필요하며 액세스 권한을 부여하려면 어떻게해야합니까?
최신 정보:
이 답변 을 기반으로 코드를 수정하여 오래된 메서드를 제거했습니다.
보안 네임 스페이스를 사용하여이를 확인할 수 있습니다.
public void ExportToFile(string filename)
{
var permissionSet = new PermissionSet(PermissionState.None);
var writePermission = new FileIOPermission(FileIOPermissionAccess.Write, filename);
permissionSet.AddPermission(writePermission);
if (permissionSet.IsSubsetOf(AppDomain.CurrentDomain.PermissionSet))
{
using (FileStream fstream = new FileStream(filename, FileMode.Create))
using (TextWriter writer = new StreamWriter(fstream))
{
// try catch block for write permissions
writer.WriteLine("sometext");
}
}
else
{
//perform some recovery action here
}
}
이러한 권한을 얻는 한 사용자에게 어떻게 든 그렇게하도록 요청해야합니다. 프로그래밍 방식으로이 작업을 수행 할 수 있다면 모두 문제가 될 것입니다.)
코드가 다음을 수행 할 때 :
- 현재 사용자에게 작업 권한이 있는지 확인합니다.
- 1에서 체크 한 자격이 필요한 작업을 수행합니다.
런타임에 시스템에서 어떤 일이 발생할지 예측할 수 없기 때문에 권한이 1 과 2 사이에서 변경 될 위험 이 있습니다. 따라서 이전에 권한을 확인한 경우에도 UnauthorisedAccessException 이 throw 되는 상황을 코드에서 처리해야합니다 .
점을 유의 의 SecurityManager 클래스 CAS 권한을 확인하는 데 사용되며, 실제로 현재 사용자 (ACL 및 ACE를 통해)이 지정된 위치에 쓰기 권한을 가지고 있는지 OS 확인하지 않는다. 따라서 IsGranted 는 로컬에서 실행되는 응용 프로그램에 대해 항상 true를 반환합니다.
예 ( Josh의 예 에서 파생 됨 ) :
//1. Provide early notification that the user does not have permission to write.
FileIOPermission writePermission = new FileIOPermission(FileIOPermissionAccess.Write, filename);
if(!SecurityManager.IsGranted(writePermission))
{
//No permission.
//Either throw an exception so this can be handled by a calling function
//or inform the user that they do not have permission to write to the folder and return.
}
//2. Attempt the action but handle permission changes.
try
{
using (FileStream fstream = new FileStream(filename, FileMode.Create))
using (TextWriter writer = new StreamWriter(fstream))
{
writer.WriteLine("sometext");
}
}
catch (UnauthorizedAccessException ex)
{
//No permission.
//Either throw an exception so this can be handled by a calling function
//or inform the user that they do not have permission to write to the folder and return.
}
원시 ACL ( System.Security.AccessControl 클래스를 통해 사용할 수있는 모든 것)을 기반으로 폴더에서 유효한 권한을 프로그래밍 방식으로 계산하는 것은 까다 롭고 권장되지 않습니다 . Stack Overflow 및 더 넓은 웹에 대한 다른 답변은 권한이 허용되는지 여부를 알기 위해 작업을 수행하는 것이 좋습니다. 이 게시물은 권한 계산을 구현하는 데 필요한 사항을 요약하고이 작업을 수행하는 데 충분해야합니다.
MaxOvrdrv의 Code 의 고정 버전입니다 .
public static bool IsReadable(this DirectoryInfo di)
{
AuthorizationRuleCollection rules;
WindowsIdentity identity;
try
{
rules = di.GetAccessControl().GetAccessRules(true, true, typeof(SecurityIdentifier));
identity = WindowsIdentity.GetCurrent();
}
catch (UnauthorizedAccessException uae)
{
Debug.WriteLine(uae.ToString());
return false;
}
bool isAllow = false;
string userSID = identity.User.Value;
foreach (FileSystemAccessRule rule in rules)
{
if (rule.IdentityReference.ToString() == userSID || identity.Groups.Contains(rule.IdentityReference))
{
if ((rule.FileSystemRights.HasFlag(FileSystemRights.Read) ||
rule.FileSystemRights.HasFlag(FileSystemRights.ReadAttributes) ||
rule.FileSystemRights.HasFlag(FileSystemRights.ReadData)) && rule.AccessControlType == AccessControlType.Deny)
return false;
else if ((rule.FileSystemRights.HasFlag(FileSystemRights.Read) &&
rule.FileSystemRights.HasFlag(FileSystemRights.ReadAttributes) &&
rule.FileSystemRights.HasFlag(FileSystemRights.ReadData)) && rule.AccessControlType == AccessControlType.Allow)
isAllow = true;
}
}
return isAllow;
}
public static bool IsWriteable(this DirectoryInfo me)
{
AuthorizationRuleCollection rules;
WindowsIdentity identity;
try
{
rules = me.GetAccessControl().GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));
identity = WindowsIdentity.GetCurrent();
}
catch (UnauthorizedAccessException uae)
{
Debug.WriteLine(uae.ToString());
return false;
}
bool isAllow = false;
string userSID = identity.User.Value;
foreach (FileSystemAccessRule rule in rules)
{
if (rule.IdentityReference.ToString() == userSID || identity.Groups.Contains(rule.IdentityReference))
{
if ((rule.FileSystemRights.HasFlag(FileSystemRights.Write) ||
rule.FileSystemRights.HasFlag(FileSystemRights.WriteAttributes) ||
rule.FileSystemRights.HasFlag(FileSystemRights.WriteData) ||
rule.FileSystemRights.HasFlag(FileSystemRights.CreateDirectories) ||
rule.FileSystemRights.HasFlag(FileSystemRights.CreateFiles)) && rule.AccessControlType == AccessControlType.Deny)
return false;
else if ((rule.FileSystemRights.HasFlag(FileSystemRights.Write) &&
rule.FileSystemRights.HasFlag(FileSystemRights.WriteAttributes) &&
rule.FileSystemRights.HasFlag(FileSystemRights.WriteData) &&
rule.FileSystemRights.HasFlag(FileSystemRights.CreateDirectories) &&
rule.FileSystemRights.HasFlag(FileSystemRights.CreateFiles)) && rule.AccessControlType == AccessControlType.Allow)
isAllow = true;
}
}
return isAllow;
}
죄송합니다. 이전 솔루션 중 어느 것도 도움이되지 않았습니다. SecurityManager와 SO 권한을 모두 확인해야합니다. Josh 코드와 iain 답변으로 많은 것을 배웠지 만 Rakesh 코드를 사용해야하는 것이 두렵습니다 (또한 그 덕분에). 단 하나의 버그 : 그는 허용 만 확인하고 거부 권한은 확인하지 않습니다. 그래서 제 제안은 :
string folder;
AuthorizationRuleCollection rules;
try {
rules = Directory.GetAccessControl(folder)
.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));
} catch(Exception ex) { //Posible UnauthorizedAccessException
throw new Exception("No permission", ex);
}
var rulesCast = rules.Cast<FileSystemAccessRule>();
if(rulesCast.Any(rule => rule.AccessControlType == AccessControlType.Deny)
|| !rulesCast.Any(rule => rule.AccessControlType == AccessControlType.Allow))
throw new Exception("No permission");
//Here I have permission, ole!
이것이 닫히지 않았기 때문에 제대로 작동하는 것을 찾는 모든 사람을 위해 새 항목을 제출하고 싶습니다. 여기에서 찾은 내용을 합쳐서 DirectoryServices를 사용하여 코드 자체를 디버깅하고 사용할 적절한 코드, 모든 상황에서 나를 위해 작동하는 것을 찾았습니다. 내 솔루션은 DirectoryInfo 개체를 확장합니다 ... :
public static bool IsReadable(this DirectoryInfo me)
{
AuthorizationRuleCollection rules;
WindowsIdentity identity;
try
{
rules = me.GetAccessControl().GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));
identity = WindowsIdentity.GetCurrent();
}
catch (Exception ex)
{ //Posible UnauthorizedAccessException
return false;
}
bool isAllow=false;
string userSID = identity.User.Value;
foreach (FileSystemAccessRule rule in rules)
{
if (rule.IdentityReference.ToString() == userSID || identity.Groups.Contains(rule.IdentityReference))
{
if ((rule.FileSystemRights.HasFlag(FileSystemRights.Read) ||
rule.FileSystemRights.HasFlag(FileSystemRights.ReadAndExecute) ||
rule.FileSystemRights.HasFlag(FileSystemRights.ReadAttributes) ||
rule.FileSystemRights.HasFlag(FileSystemRights.ReadData) ||
rule.FileSystemRights.HasFlag(FileSystemRights.ReadExtendedAttributes) ||
rule.FileSystemRights.HasFlag(FileSystemRights.ReadPermissions)) && rule.AccessControlType == AccessControlType.Deny)
return false;
else if ((rule.FileSystemRights.HasFlag(FileSystemRights.Read) ||
rule.FileSystemRights.HasFlag(FileSystemRights.ReadAndExecute) ||
rule.FileSystemRights.HasFlag(FileSystemRights.ReadAttributes) ||
rule.FileSystemRights.HasFlag(FileSystemRights.ReadData) ||
rule.FileSystemRights.HasFlag(FileSystemRights.ReadExtendedAttributes) ||
rule.FileSystemRights.HasFlag(FileSystemRights.ReadPermissions)) && rule.AccessControlType == AccessControlType.Allow)
isAllow = true;
}
}
return isAllow;
}
public static bool IsWriteable(this DirectoryInfo me)
{
AuthorizationRuleCollection rules;
WindowsIdentity identity;
try
{
rules = me.GetAccessControl().GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));
identity = WindowsIdentity.GetCurrent();
}
catch (Exception ex)
{ //Posible UnauthorizedAccessException
return false;
}
bool isAllow = false;
string userSID = identity.User.Value;
foreach (FileSystemAccessRule rule in rules)
{
if (rule.IdentityReference.ToString() == userSID || identity.Groups.Contains(rule.IdentityReference))
{
if ((rule.FileSystemRights.HasFlag(FileSystemRights.Write) ||
rule.FileSystemRights.HasFlag(FileSystemRights.WriteAttributes) ||
rule.FileSystemRights.HasFlag(FileSystemRights.WriteData) ||
rule.FileSystemRights.HasFlag(FileSystemRights.WriteExtendedAttributes) ||
rule.FileSystemRights.HasFlag(FileSystemRights.CreateDirectories) ||
rule.FileSystemRights.HasFlag(FileSystemRights.CreateFiles)) && rule.AccessControlType == AccessControlType.Deny)
return false;
else if ((rule.FileSystemRights.HasFlag(FileSystemRights.Write) ||
rule.FileSystemRights.HasFlag(FileSystemRights.WriteAttributes) ||
rule.FileSystemRights.HasFlag(FileSystemRights.WriteData) ||
rule.FileSystemRights.HasFlag(FileSystemRights.WriteExtendedAttributes) ||
rule.FileSystemRights.HasFlag(FileSystemRights.CreateDirectories) ||
rule.FileSystemRights.HasFlag(FileSystemRights.CreateFiles)) && rule.AccessControlType == AccessControlType.Allow)
isAllow = true;
}
}
return me.IsReadable() && isAllow;
}
None of these worked for me.. they return as true, even when they aren't. The problem is, you have to test the available permission against the current process user rights, this tests for file creation rights, just change the FileSystemRights clause to 'Write' to test write access..
/// <summary>
/// Test a directory for create file access permissions
/// </summary>
/// <param name="DirectoryPath">Full directory path</param>
/// <returns>State [bool]</returns>
public static bool DirectoryCanCreate(string DirectoryPath)
{
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 ((FileSystemRights.CreateFiles & rule.FileSystemRights) == FileSystemRights.CreateFiles)
{
if (rule.AccessControlType == AccessControlType.Allow)
return true;
}
}
}
}
catch {}
return false;
}
You can try following code block to check if the directory is having Write Access.
It checks the 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
}
Wow...there is a lot of low-level security code in this thread -- most of which did not work for me, either -- although I learned a lot in the process. One thing that I learned is that most of this code is not geared to applications seeking per user access rights -- it is for Administrators wanting to alter rights programmatically, which -- as has been pointed out -- is not a good thing. As a developer, I cannot use the "easy way out" -- by running as Administrator -- which -- I am not one on the machine that runs the code, nor are my users -- so, as clever as these solutions are -- they are not for my situation, and probably not for most rank and file developers, either.
Like most posters of this type of question -- I initially felt it was "hackey", too -- I have since decided that it is perfectly alright to try it and let the possible exception tell you exactly what the user's rights are -- because the information I got did not tell me what the rights actually were. The code below -- did.
Private Function CheckUserAccessLevel(folder As String) As Boolean
Try
Dim newDir As String = String.Format("{0}{1}{2}",
folder,
If(folder.EndsWith("\"),
"",
"\"),
"LookWhatICanDo")
Dim lookWhatICanDo = Directory.CreateDirectory(newDir)
Directory.Delete(newDir)
Return True
Catch ex As Exception
Return False
End Try
End Function
'IT TIP' 카테고리의 다른 글
Angular 2 빠른 시작 : 예기치 않은 토큰 < (0) | 2020.12.07 |
---|---|
ExecutorService의 활성 스레드 (0) | 2020.12.07 |
VBA에서 문자열을 어떻게 연결할 수 있습니까? (0) | 2020.12.07 |
Team Foundation Build 또는 TeamCity? (0) | 2020.12.07 |
간단한 삽입 문을 사용하여 바이너리 파일 데이터를 바이너리 SQL 필드에 삽입하려면 어떻게해야합니까? (0) | 2020.12.06 |