System.UnauthorizedAccessException - 访问路径被拒绝
这是一个有点棘手的问题,所以请耐心等待...
我有一个简单的小方法:
Public Overloads Shared Function DoStuff(ByVal path As String) As Boolean
If Not IO.File.Exists(ipath) Then Throw New ArgumentException
Dim result As Boolean
Using fs As FileStream = New FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)
' do stuff here, details are not important
fs.Close()
End Using
Return result
End Function
我很欣赏该方法没有显示如何使用流,但细节无关紧要,我将在下面解释。
该方法紧贴在类库中;我们在各种其他项目中引用的Helper。显然,在大多数情况下,假设路径有效、可访问等,代码应该看起来不错。
现在,问题来了。我有一个 WCF 服务库,它引用并使用 Helper 程序集中的上述方法。 WCF 服务库托管在 Windows 服务中,而 Windows 服务又驻留在我们的一台服务器上。 WCF 服务有一个操作,用于接收文件的 UNC 路径,并在正常流程中调用帮助程序类中的上述方法。
我发送的路径是我们网络上共享的文件的路径。 “Using fs As...”行失败,并出现以下异常:
System.UnauthorizedAccessException:拒绝访问路径“此处列出了我的文件路径”。在 System.IO.__Error.WinIOError(Int32 errorCode, String MaybeFullPath) 在 System.IO.FileStream.Init(字符串路径、FileMode 模式、FileAccess 访问、Int32 权限、布尔 useRights、FileShare 共享、Int32 bufferSize、FileOptions 选项、SECURITY_ATTRIBUTES secAttrs 、字符串 msgPath、布尔值 bFromProxy、布尔值 useLongPath) at System.IO.FileStream..ctor(字符串路径,FileMode模式,FileAccess访问,FileShare共享,Int32 bufferSize,FileOptions选项,String msgPath,布尔bFromProxy)在System.IO.FileStream..ctor(字符串路径,FileMode模式)在MyHelperAssemblyName.DoStuff(String filePath) 异常的其余部分是指向方法、程序集、wcf 服务等的堆栈跟踪”
现在,列出我尝试诊断问题的内容(包括愚蠢的明显步骤):
将堆栈跟踪中列出的路径复制并粘贴到 Windows 资源管理器(在我的本地计算机和服务器上)以确保文件存在并且可以访问 --> 能够访问该文件
确保 Windows 服务的帐户对该文件有足够的权限来读取 --> 有效权限将服务帐户列为具有完全控制权
将 Windows 服务的帐户更改为使用我的个人管理员帐户(临时措施),并显然重新启动服务以使更改生效 --> 同一行代码失败
将包含文件的目录复制到我的本地计算机,然后针对我的本地计算机运行该服务(我们希望确保托管该文件的 NAS 不是原因)--> 同一行代码失败
创建一个快速控制台应用程序,将辅助程序集方法中的代码复制粘贴到应用程序中,注入相同的文件路径,在本地运行,然后在服务器上运行(在服务器上,我的意思是使用我之前提到的相同管理员帐户远程连接到服务器,然后运行它)--> 应用程序运行代码没有问题
创建控制台应用程序并使用在控制台应用程序中托管 WCF 服务库的批量标准方式。在本地运行应用程序,然后针对我指定为基址的本地地址使用 WcfStorm控制台应用程序的地址,使用正常服务失败的相同路径调用相同的方法 --> WcfStorm 的结果确认代码没有问题
仔细检查 WCF 服务库的代码,确保不存在任何会影响我的测试的特殊条件逻辑 --> 辅助方法几乎在服务操作实现启动后立即调用(就在参数验证之后)。如果不运行辅助方法,该操作就不可能返回一致的结果,因此当我之前收到一致的结果并假设“奇怪的”文件访问代码已运行时,它实际上已经运行了< /p>
- < p>通过干净重建 Windows 服务主机、WCF 服务库和帮助程序集来重新部署服务(想要确保屏幕上的代码实际上是服务器上运行的代码)--> 没有变化
编辑2011-06-24 16:32GMT - 使用我之前创建的控制台应用程序来托管WCF服务,相应地调整baseAddress并部署在服务器。使用与上述相同的管理员帐户运行应用程序。使用 WcfStorm 在新基地址上测试新应用程序。 --> 代码按预期工作并返回良好的结果(我相信在现阶段将其范围缩小为 Windows 服务的错误?)
编辑 2011-06-27 10:21GMT< /strong> - 创建一个简单的 Windows 服务,引用帮助程序类。安装在Server上,该服务的帐户设置为与Live Server相同。 --> 新服务能够运行代码并访问文件
编辑 2011-06-27 10:23GMT - 服务已经工作了,我很恼火,我打开了WcfStorm 我周末一直在运行。周五显示的结果仍然显示现场服务失败。我重新发送了同样的请求 --> 它起作用了......我实际上现在更恼火,因为我没有真正的方法来跟踪问题
因此,该服务目前工作正常。任何人都知道什么会导致这种间歇性故障?同事向我保证周末没有任何改变(至少不是手动改变)。迷惑了……
This is a slightly tricky one, so bear with me...
I have a simple little method:
Public Overloads Shared Function DoStuff(ByVal path As String) As Boolean
If Not IO.File.Exists(ipath) Then Throw New ArgumentException
Dim result As Boolean
Using fs As FileStream = New FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)
' do stuff here, details are not important
fs.Close()
End Using
Return result
End Function
I appreciate that the method does not show how the stream is used, but the details are irrelevant as I'll explain below.
This method is sat snuggly in a Class Library; a Helper which we reference in a variety of other projects. Clearly, for the most part that code should look fine on the assumption the path is valid, accessible, etc.
Now, the issue. I have a WCF Service Library that references and consumes the aforementioned Method in the Helper assembly. The WCF Service Library is hosted within a Windows Service, which in turn resides on one of our servers. The WCF Service has an Operation that receives a UNC Path for a file, and during normal flow, calls the method above in the Helper Class.
The path I send is for a file, on a share, on our network. The line "Using fs As..." fails with the following exception:
System.UnauthorizedAccessException: Access to the path 'my file path is listed here' is denied. at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath) at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy) at System.IO.FileStream..ctor(String path, FileMode mode) at MyHelperAssemblyName.DoStuff(String filePath) in the rest of the exception is a stack trace pointing to the method, assembly, wcf service, etc"
Now, a list of things I have tried to diagnose the issue (including the stupidly obvious steps):
Copy and Paste the path listed in the Stack Trace into Windows Explorer (both on my local machine and the server) to ensure the file exists and is accessible --> Able to Access the file
Ensure that the Windows Service's account has sufficient permission on the file to read --> Effective Permissions lists the Service's Account as having Full Control
Change the Windows Service's account to use my personal admin account (temporary measure) and obviously restart the service for changes to take effect --> The same line of code fails
Copy the Directory containing the file to my local machine, and run the service against my local machine (we wanted to ensure that the NAS which hosts the file wasn't the cause) --> The same line of code fails
Create a quick console application, copy paste the code from the helper assembly's method into the application, inject the same file path, run it locally and then on the server (by on the server, I mean remote connect to the server using the same Admin account I mentioned earlier, and run it) --> The application has no problems running the code
Create a Console Application and use the bulk standard way of hosting the WCF Service Library within the Console Application. Run the Application locally, and then, using WcfStorm against the local address I specified as the base address for the console app, call the same method with the same path that the normal service fails on --> The results from WcfStorm confirm that the code had no problems
Double check the WCF Service Library's code to ensure that there isn't any perculiar conditional logic that would effect my tests --> The Helper Method is called almost immediately after the Service Operation Implementation starts (just after argument validation). It is not possible for the operation to return coherent results without running through the helper method so when I had been receiving coherent results previously and assumed the "weird" file access code had been run, it had, infact been run
Re-deployed the Service with clean rebuilds of the Windows Service Host, WCF Service Library, and Helper Assembly (wanted to make sure the code on my screen was infact the code that was running on the server) --> No change
EDIT 2011-06-24 16:32GMT - Using the console app I created earlier to host the WCF service, adjust the baseAddress accordingly and deploy on the server. Run the app using the same Admin account as mentioned above. Test the new app on the new base address using WcfStorm. --> Code works as expected and returns good results (I believe at this stage narrowing it down to being the fault of the Windows Service?)
EDIT 2011-06-27 10:21GMT - Created a simple Windows Service, referencing the helper class. Installed on the Server, the service's account set to the the same as the Live Server. --> The new Service was able to run the code and access the file
EDIT 2011-06-27 10:23GMT - Annoyed that the service had worked, I pulled open WcfStorm which I had left running over the weekend. The results were stills displayed from Friday showing the live service had failed. I resent the same request --> It worked... I'm actually more annoyed now because I have no real means of tracking the issue
So, the service is for now working correctly. Anyone have any ideas what would cause such an intermittent failing? I'm assured by co-workers that nothing was changed over the weekend (not manually at least). Baffled...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
尝试进程监视器。它将显示哪个用户正在访问该文件以及返回的特定 Windows 错误代码。然后您应该能够明白为什么它对某些文件有效而对其他文件无效。
Try process monitor. It will show you what user is accessing the file and the specific windows error code that is being returned. Then you should be able to see why it is working for some files and not others.
当我的代码访问尚未完全写入磁盘的新文件时,我遇到了类似的情况。所以等待几毫秒就解决了我的问题。您是否有可能在将流完全写入磁盘之前尝试读取该流?
I had something similar when my code was accessing a new file which wasn't yet fully written to disk. So waiting a few milliseconds solved it for me. Is it possible that you are trying to read that stream before it's being completely written to disk?
您的 WCF 服务是否使用模拟?
这可以解释为什么新的 Windows 服务可以执行该操作,但 WCF 服务却不能。新服务直接针对 NAS 进行身份验证。如果在旧服务中,WCF 模拟调用者,客户端计算机对用户进行身份验证,他们的令牌将传递到您的 WCF 服务,WCF 服务又将安全令牌传递到 NAS,然后您点击 双跳问题。
您可以将活动安全上下文恢复到服务帐户,如下所示:
当然,这并不能解释为什么它可能会间歇性地工作。但它可以解释 WCF 服务在托管它的计算机上本地调用时工作,而不是从远程客户端计算机上调用。
Does your WCF Service use impersonation?
This would explain why the new windows service can perform the action but the WCF service could not. The new service authenticates directly against the NAS. If in the old service, WCF were impersonating the caller, the client computer authenticates the user, their token is passed to your WCF service, which in turn passes the security token to the NAS, and you hit the double hop problem.
You can make the active security context revert to the service account like this:
Of course, this doesn't explain why it might have been working intermittently. But it would explain the WCF service working when invoked locally on the machine that is hosting it, but not from a remote client machine.
我有一些预感。
您是否尝试过将“FileAccess.Read”和/或“FileShare.Read”设置为“ReadWrite”?
另外,这个警告是否可能是一个因素?来自http://msdn.microsoft.com/en-us/library/5h0z48dh。 .aspx:
I have a few hunches.
Have you tried setting 'FileAccess.Read' and/or 'FileShare.Read' to 'ReadWrite'?
Also, is it possible this warning could be a factor? From http://msdn.microsoft.com/en-us/library/5h0z48dh.aspx: