解决System.Threading.Tasks.Task用户身份模拟(identity impersonate)的问题
在解决了ASP.NET访问共享文件夹的问题之后,我们遇到了一个新的问题。在找找看(http://zzk.cnblogs.com/)调度建立索引过程中,在共享文件夹中创建新文件夹时出现错误:
System.UnauthorizedAccessException: Access to the path '\\192.168.18.18\ZzkIndex\Job\JobOffer\' is denied.
之前我们明明通过测试代码验证了可以在共享文件夹中建立文件夹的,现在怎么不行呢?
唯一不同之处在于这个操作是在System.Threading.Tasks.Task中进行的,也就是异步的。
前一篇文章中访问共享文件夹时,用户身份是通过web.config中的设置模拟的:
<system.web>
<identity impersonate="true" userName="ZzkIndexer" password="zzk.cnblogs.com"/>
</system.web>
现在出现UnauthorizedAccess异常,很有可能是在Task中异步执行时,不是以ZzkIndexer这个用户身份执行的。
于是,从这个地方下手,把要解决的问题变为:“如何在异步操作中也一直使用web.config中所设置的模拟用户身份?”
在互联网海洋中苦苦寻觅。。。终于找到了线索!它就是 —— <alwaysFlowImpersonationPolicy> 。
它的藏身之处是 C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Aspnet.config
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<runtime>
<legacyUnhandledExceptionPolicy enabled="false" />
<legacyImpersonationPolicy enabled="true"/>
<alwaysFlowImpersonationPolicy enabled="false"/>
<SymbolReadingPolicy enabled="1" />
<shadowCopyVerifyByTimestamp enabled="true"/>
</runtime>
<startup useLegacyV2RuntimeActivationPolicy="true" />
</configuration>
MSDN中对alwaysFlowImpersonationPolicy的介绍:
Specifies that the Windows identity always flows across asynchronous points, regardless of how impersonation was performed.
指定无论模拟是如何执行的,Windows 标识始终流经异步点。
与alwaysFlowImpersonationPolicy相对应的是legacyImpersonationPolicy,MSDN中的介绍:
Specifies that the Windows identity does not flow across asynchronous points, regardless of the flow settings for the execution context on the current thread.
指定无论当前线程上的执行上下文的流设置如何,Windows 标识都不流经异步点。
于是,问题的解决方法显而易见,在Aspnet.config中将alwaysFlowImpersonationPolicy设为true,将legacyImpersonationPolicy设为false,完整设置如下:
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<runtime>
<legacyUnhandledExceptionPolicy enabled="false" />
<legacyImpersonationPolicy enabled="false"/>
<alwaysFlowImpersonationPolicy enabled="true"/>
<SymbolReadingPolicy enabled="1" />
<shadowCopyVerifyByTimestamp enabled="true"/>
</runtime>
<startup useLegacyV2RuntimeActivationPolicy="true" />
</configuration>
经过实际检验,该方法确实有效,目前为止未发现任何副作用。
(注:修改Aspnet.config后,需要重启当前Web站点才能生效)