我有一个程序,使用如下所示的方法将一些数据写入文件.
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) System.IO.FileStream..ctor中的String String msgPath,Boolean bFromProxy(字符串路径,FileMode模式,FileAccess访问FileShare共享,Int32 bufferSize,FileOptions选项,字符串msgPath,Boolea bFromProxy)
问题:我需要使用哪些代码来获取此信息以及如何授予访问权限?
更新:
修改了基于此答案的代码,以摆脱过时的方法.
您可以使用Security命名空间来检查:
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. }
这很棘手,不建议尝试以编程方式根据原始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代码(也要感谢他).只有一个bug:我发现他只检查Allow而不是Deny权限.所以我的提议是:
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(); 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!