你如何检查写入目录或文件的权限?
我有一个程序,使用下面的方法将一些数据写入文件。
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); } }
运行程序时,出现错误:
未处理的exception:System.UnauthorizedAccessException:对path“mypath”的访问被拒绝。 (System.IO.FileStream.Init(String path,FileMode mode,FileAccess access,nt32 rights,Boolean useRights,FileShare share,Int32 bufferSize,FileOptions ptions,SECURITY_ATTRIBUTES secAttrs)在System.IO中.__ Error.WinIOError(Int32 errorCode,String maybeFullPath) ,stringmsgPath,布尔型bFromProxy)在System.IO.FileStream..ctor(stringpath,FileMode模式,FileAccess访问FileShare共享,Int32 bufferSize,FileOptions选项,stringmsgPath,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的情况。
请注意, SecurityManager类用于检查CAS权限,并不实际检查操作系统当前用户是否具有对指定位置的写入访问权限(通过ACL和ACE)。 因此, 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. }
这是棘手的, 不build议尝试以基于原始ACL(通过System.Security.AccessControl类可用的所有)从文件夹编程计算有效权限。 其他堆栈溢出和更广泛的网页上的答案build议尝试执行行动,以知道是否允许的权限。 这篇文章总结了实现权限计算所需的内容,并且足以让您避免这样做。
对不起,但以前的解决scheme没有帮助我。 我需要检查双方:SecurityManager和SO权限。 我用Josh代码和iain的答案学到了很多东西,但是恐怕我需要使用Rakesh代码(也感谢他)。 只有一个错误:我发现他只检查允许而不是拒绝权限。 所以我的build议是:
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!
由于这不是封闭的,我想提交一个新的条目,任何人都希望有适当的东西为他们工作…使用我在这里find的合并,以及使用DirectoryServicesdebugging代码本身,并find正确的代码使用,这里是我发现,在任何情况下适用于我…请注意,我的解决scheme扩展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; }
它是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; }
这些都没有为我工作..他们返回真实的,即使他们没有。 问题是,您必须针对当前进程用户权限testing可用权限,这将testing文件创build权限,只需将FileSystemRights子句更改为“写入”以testing写入权限即可。
/// <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 }
哇…这个线程中有很多低级别的安全代码,其中大部分都不适合我,虽然我在这个过程中学到了很多东西。 我学到的一件事是,这些代码大部分不是针对寻求每个用户访问权限的应用程序的 – 这是为了pipe理员想要以编程方式改变权限,正如已经指出的那样,这不是一件好事。 作为一名开发人员,我不能使用“简单的出路” – 以pipe理员身份运行 – 我不是一个运行代码的机器,也不是我的用户 – 因此,像这些解决scheme一样聪明 – 他们不适合我的情况,可能也不适合大多数职位和文件开发人员。
就像大多数这类问题的海报一样 – 我最初也觉得这也是“黑客” – 我从那以后就决定完全可以尝试一下,让可能的例外告诉你用户的权利是什么 – 因为我得到的信息并没有告诉我实际上是什么权利。 下面的代码 – 做到了。
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
结束function