2008-09-24 94 views
52

我有一個程序,使用下面的方法將一些數據寫入文件。如何檢查寫入目錄或文件的權限?


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); 


    } 
} 

運行程序時,我得到一個錯誤:

Unhandled Exception: System.UnauthorizedAccessException: Access to the path 'mypath' is denied. at 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)

問:我需要趕上這一點,我怎麼授予什麼代碼的訪問?

回答

60

UPDATE:

修改的基礎上this answer代碼擺脫過時的方法。

您可以使用安全命名空間進行檢查:

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 
    } 

} 

至於那些獲得許可,你將不得不要求用戶爲你做的莫名其妙。如果你能編程做到這一點,那麼我們都會有麻煩;)

+5

此解決方案不起作用,SecurityManager.IsGranted即使我沒有對文件的寫權限返回true(Win XP的SP3) – 2010-01-07 13:54:56

+1

你運行本地管理員,或作爲無權訪問的權限較低的用戶? – Josh 2010-01-08 03:58:10

+2

SecurityManager.IsGranted歸因於已廢棄。這個答案可能不會永久工作。 – MarkPflug 2011-08-03 17:35:19

29

當你的代碼執行以下操作:

  1. 檢查當前用戶有權限做一些事情。
  2. 貫徹執行需要的權利在1

檢查您運行的權限和之間改變,因爲你無法預知什麼其他將在被髮生的危險動作系統在運行時。因此,即使您之前已檢查過權限,您的代碼也應處理出現以下情況:引發了UnauthorisedAccessException

請注意,SecurityManager類用於檢查CAS權限,並不實際檢查操作系統當前用戶是否具有對指定位置(通過ACL和ACE)的寫入訪問權限。因此,對於本地運行的應用程序,IsGranted將始終返回true。

(從Josh's example派生):

//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類)。堆棧溢出和更廣泛的網絡上的其他答案建議嘗試執行操作以瞭解是否允許權限。 This後總結了實施權限計算所需的內容,並且應該足以讓您避免這樣做。

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     
      } 
6

對不起,但以前的解決方案沒有幫助我。我需要檢查雙方: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! 
3

沒有這些爲我工作..他們返回爲真,即使他們沒有。問題是,你必須測試針對當前進程的用戶權限的可用許可,該測試文件創建權限,只是FileSystemRights條款更改爲「寫入」將試寫訪問..

/// <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; 
} 
4

由於這ISN關閉,我想提交一個新的條目,任何人都希望有一些適合他們的工作......使用我在這裏找到的東西的合併,以及使用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; 
    } 
5

它是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; 
} 
0

哇...有在這個線程很多低級別的安全代碼 - 其中大部分沒有工作對我來說,無論是 - 雖然我學到了很多在這個過程中。我瞭解到的一件事是,這些代碼大部分不是針對尋求每個用戶訪問權限的應用程序的 - 針對管理員希望以編程方式更改權限,正如已經指出的那樣 - 是而不是是一件好事。作爲一名開發人員,我不能使用「簡單的出路」 - 以管理員身份運行 - 我不是那種運行代碼的機器,也不是我的用戶 - 因此,像這些解決方案一樣聰明 - 它們不適合我的情況,也可能不適用於大多數排名和文件開發人員。

就像大多數這類問題的海報一樣 - 我最初也覺得它也是「hackey」 - 我從那以後就決定試試它是完全沒錯的,讓可能的例外告訴你究竟是什麼用戶的權利是 - 因爲我得到的信息並沒有告訴我實際上的權利。下面的代碼 - 做到了。

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 

端功能