56

나는 아래와 같은 메소드를 사용하여 파일에 데이터를 쓰는 프로그램을 가지고있다.


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)

질문 :이 코드를 잡으려면 어떤 코드가 필요하며 어떻게 액세스 권한을 부여합니까?

8 답변


63

최신 정보:

다음을 기준으로 코드 수정이 대답쓸데없는 방법을 제거합니다.

보안 네임 스페이스를 사용하여이를 확인할 수 있습니다.

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
    }

}

그 허가를 얻는 한, 당신은 어떻게 든 당신을 위해 그것을하도록 사용자에게 요구해야 할 것입니다. 프로그래밍 방식으로이 작업을 수행 할 수 있다면 문제가 발생할 수 있습니다.)


  • 이 솔루션은 작동하지 않습니다. SecurityManager.IsGranted는 파일에 대한 쓰기 권한이 없어도 true를 반환합니다 (Win XP SP3). - Thomas Levesque
  • 로컬 관리자 또는 액세스 권한이없는 권한이 적은 사용자로 실행하고 있습니까? - Josh
  • SecurityManager.IsGranted는 Obsolete로 간주됩니다. 이 대답은 영원히 작동하지 않을 수도 있습니다. - MarkPflug
  • @ 제트 노어 - 찾고 있습니다SecurityManager.IsGranted방법. 4.0에서 더 이상 사용하지 않는 것이 좋습니다.PermissionSets. 위의 코드는 크게 다르지 않지만PermissionSet한 번에 하나의 사용 권한 만 검사합니다. - Josh
  • @ 조쉬가 귀하의 PC에서이 작업을 시도해보십시오 ... 새 폴더를 생성하십시오 (관리자, 모든 권한이 있고 관리자 그룹에 포함되어 있는지 확인). 그런 다음 보안 목록에 자신 / Windows 계정을 추가 한 다음 당신의 권리를 편집하고 Write on Deny를 넣으세요. 당신의 메소드는 쓰기를 True로, 관리자는 쓰기 권한을 가지고 Deny는 당신의 계정 엔트리보다 우선합니다. 따라서, 당신의 방법은 나를 위해 작동하지 않습니다 ... 내 대답을 참조하십시오. - MaxOvrdrv

30

코드가 다음을 수행 할 때 :

  1. 현재 사용자에게 무언가를 수행 할 수있는 권한이 있는지 확인합니다.
  2. 1에서 점검 한 권한 부여가 필요한 조치를 수행합니다.

사용 권한이 변경되는 위험을 실행합니다.12왜냐하면 런타임에 시스템에서 어떤 일이 일어날 지 예측할 수 없기 때문입니다. 따라서 코드에서 다음과 같은 상황을 처리해야합니다.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와 더 넓은 웹에 대한 다른 해답은 권한이 허용되는지 여부를 알기위한 조치를 취하는 것이 좋습니다.게시물은 권한 계산을 구현하는 데 필요한 것을 요약하며이를 수행하는 데 충분해야합니다.


  • 이 철학은 모두 훌륭하고 훌륭하지만 보편적으로 일하지 않습니다. 예를 들어, 사용자가 쓰기를 원하는 폴더의 경로를 선택하는 대화 상자를 보여줄 필요가 있습니다. 대화 상자에 제안 된 의미있는 초기 값을 입력하고 싶습니다. 존재하지 않습니다. 이전 버전과의 호환성을 위해 기본 경로는 & quot; C : \ & lt; SomeName & gt;입니다. 사용자가 거기에 쓸 수 없다면 AppData에서 기본값으로 되돌아 가고 싶습니다. 폴더 찾아보기 대화 상자의 초기 값을 결정하기 위해 폴더를 만들고 다시 삭제할 방법이 없습니다. - Roger Sanders
  • @ LogerSanders - 좋은 지적. - Iain

8

그것의 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;
}


  • 이것은 나를 위해 실제로 일했습니다! 감사! - Smartis
  • 이것은 정말로 효과가 있었다! 나는 선택한 답변이 응용 프로그램이 아닌 로그인 한 사용자를 기반으로 권한을 추측 한 것 같습니다. - ibocon
  • 이 작품! 나는 확인했다.C:\Program Files\...내 응용 프로그램을 관리자 권한으로 실행하지 않아도됩니다.IsWriteable()이 경우 false를 반환합니다. - arnobpl

6

미안하지만, 이전 솔루션 중 아무도 나를 도왔습니다. 나는 양쪽면을 검사 할 필요가있다 : 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!



4

이것은 닫히지 않았기 때문에, 나는 그들을 위해 올바르게 작동하는 것을 찾고있는 누군가를위한 새로운 엔트리를 제출하고 싶습니다. 여기에서 발견 한 것의 합병을 사용하고 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;
    }


  • 나는 두 가지 개선점 (IMO)을 발견했다. 첫째, IsReadable 시작 부분에 디렉토리 (me.Exists)가 있는지 확인하십시오. 둘째, IsWritable 내부에서 IsReadable 검사를 위로 이동합니다. 또한 어떤 상황에서는 파일을 쓸 수는 있지만 읽을 수는 없기 때문에 어떤 사람들은 두 방법을 "연결 해제 됨"으로 유지하기를 원할 것입니다. - K Kimble
  • 또한 메서드 호출 외부에있는 열거 형을 결합하여 정적으로 만드는 것이 효과적 일 것이라고 생각합니다. public static FileSystemRights _ReadRights = FileSystemRights.Read | FileSystemRights.ReadAndExecute | FileSystemRights.ReadAttributes | FileSystemRights.ReadData | FileSystemRights.ReadExtendedAttributes | FileSystemRights.ReadPermissions; 그런 다음 테스트 호출을 단순화하십시오. if (rule.FileSystemRights.HasFlag (_ReadRights) & amp; & amp; rule.AccessControlType == AccessControlType.Deny) - K Kimble
  • 또한 작동하지 않습니다. 해결책 없음? - Pedro77
  • 안녕하세요 @ Pedro77 - 호기심 ... 어떤 OS를 실행하고 있습니까? 저는 이것을 XP, Vista 및 Win7에서 테스트 해본 결과 세 가지 모두 완벽하게 작동합니다. Windows 8을 사용하고 있습니까? - MaxOvrdrv
  • Win7 x64. 관리자로 로그인하면 실행되지 않는 앱이 adm입니다. - Pedro77

3

이들 중 어느 것도 나를 위해 일하지 않았습니다. 그들이 그렇지 않은 경우에도 그들은 사실로 돌아갑니다. 문제는 현재 프로세스 사용자 권한에 대해 사용 가능한 권한을 테스트해야한다는 것입니다.이 경우 파일 생성 권한을 테스트하고 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;
}


  • 이것은 가장 좋은 대답입니다 ... 그러나, 당신은 2 개의 불린을 사용함으로써 Deny가 허용하는 것보다 우선한다는 것을 고려하여 코드를 수정해야합니다 ... - MaxOvrdrv
  • C : \\에 대해 true를 반환하지만 C : \\에 임의의 파일을 만들려고하면 예외가 발생합니다. - Pedro77

2

코드 블록을 따라 가면 디렉토리에 쓰기 액세스 권한이 있는지 확인할 수 있습니다.

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                 
           }


  • 작동하지 않습니다. C : \\에 대해 true를 반환하지만 C : \\에 임의의 파일을 만들려고하면 예외가 발생합니다. - Pedro77

0

와우 ...이 스레드에는 저수준 보안 코드가 많이 있습니다. 대부분이 저에게 효과적이지 않았지만, 그 과정에서 많은 것을 배웠습니다. 내가 배운 한가지 사실은이 코드의 대부분이 사용자 액세스 권한을 찾는 응용 프로그램과 관련이 없다는 것입니다. 관리자가 프로그래밍 방식으로 권한을 변경하려는 경우 - 지적 된 바와 같이아니좋은것. 개발자로서 "쉬운 방법"을 사용할 수 없습니다. 관리자로 실행하면됩니다. 코드를 실행하는 컴퓨터 나 사용자가 아니기 때문에 이러한 솔루션만큼이나 똑똑합니다. - 그들은 내 상황에 맞는 것이 아니며 대부분의 순위 및 파일 개발자에게 해당되지는 않습니다.

이런 종류의 질문에 대한 대부분의 포스터와 마찬가지로 - 나는 처음에는 "해커"라고 느꼈다. - 나는 그걸 시도하고 가능한 예외가 사용자의 권리가 무엇인지 정확하게 알려주도록 완벽하게 결정했다. 내가 얻은 정보는 실제로 그 권리가 무엇인지 말해주지 않았습니다. 아래 코드는 그랬습니다.

  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

최종 기능

연결된 질문


관련된 질문

최근 질문