나는 아래와 같은 메소드를 사용하여 파일에 데이터를 쓰는 프로그램을 가지고있다.
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) System.IO.FileStream.Init (문자열 경로, FileMode 모드, FileAccess 액세스, nt32 권한, 부울 useRights, FileShare 공유, Int32 bufferSize, FileOptions ptions, SECURITY_ATTRIBUTES secAttrs, String msgPath, 부울 bFromProxy) System.IO.FileStream ..ctor에서 (문자열 경로, FileMode 모드, FileAccess 액세스 FileShare 공유, Int32 bufferSize, FileOptions 옵션, 문자열 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과2왜냐하면 런타임에 시스템에서 어떤 일이 일어날 지 예측할 수 없기 때문입니다. 따라서 코드에서 다음과 같은 상황을 처리해야합니다.UnauthorisedAccessException이전에 사용 권한을 확인한 경우에도 throw됩니다.
참고로보안 관리자클래스는 CAS 권한을 검사하는 데 사용되며 현재 사용자가 지정된 위치 (ACL 및 ACE를 통해)에 대한 쓰기 권한이 있는지 여부를 OS와 실제로 확인하지 않습니다. 이와 같이,그랜트로컬에서 실행되는 응용 프로그램의 경우 항상 true를 반환합니다.
예(로부터 나오다조쉬의 예) :
//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의 고정 버전암호.
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 코드를 사용할 필요가 있습니다 (감사합니다). 단 하나의 버그 : 나는 그가 Allow를 거부하고 Permission을 거부하지 않는 것을 확인했다. 그래서 제 제안은 :
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;
}
이들 중 어느 것도 나를 위해 일하지 않았습니다. 그들이 그렇지 않은 경우에도 그들은 사실로 돌아갑니다. 문제는 현재 프로세스 사용자 권한에 대해 사용 가능한 권한을 테스트해야한다는 것입니다.이 경우 파일 생성 권한을 테스트하고 FileSystemRights 절을 'Write'로 변경하여 쓰기 권한을 테스트합니다.
/// <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;
}
코드 블록을 따라 가면 디렉토리에 쓰기 액세스 권한이 있는지 확인할 수 있습니다.
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
}
와우 ...이 스레드에는 저수준 보안 코드가 많이 있습니다. 대부분이 저에게 효과적이지 않았지만, 그 과정에서 많은 것을 배웠습니다. 내가 배운 한가지 사실은이 코드의 대부분이 사용자 액세스 권한을 찾는 응용 프로그램과 관련이 없다는 것입니다. 관리자가 프로그래밍 방식으로 권한을 변경하려는 경우 - 지적 된 바와 같이아니좋은것. 개발자로서 "쉬운 방법"을 사용할 수 없습니다. 관리자로 실행하면됩니다. 코드를 실행하는 컴퓨터 나 사용자가 아니기 때문에 이러한 솔루션만큼이나 똑똑합니다. - 그들은 내 상황에 맞는 것이 아니며 대부분의 순위 및 파일 개발자에게 해당되지는 않습니다.
이런 종류의 질문에 대한 대부분의 포스터와 마찬가지로 - 나는 처음에는 "해커"라고 느꼈다. - 나는 그걸 시도하고 가능한 예외가 사용자의 권리가 무엇인지 정확하게 알려주도록 완벽하게 결정했다. 내가 얻은 정보는 실제로 그 권리가 무엇인지 말해주지 않았습니다. 아래 코드는 그랬습니다.
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
최종 기능
SecurityManager.IsGranted
방법. 4.0에서 더 이상 사용하지 않는 것이 좋습니다.PermissionSets
. 위의 코드는 크게 다르지 않지만PermissionSet
한 번에 하나의 사용 권한 만 검사합니다. - Josh