在我的C#应用程序中,我使用Impersonation
来扩展用户的访问权限。为方便起见,我刚刚添加了一个public static Impersonation
对象,该对象在App启动时初始化。
Impersonation
的代码来自this answer on stackoverflow。
到目前为止,在应用程序中执行任何代码都可以正常工作:
someCodeThatNeedsImpersonation(); // Fine
somethingElse();
我现在想将代码移到BackgroundWorker
:
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += (s, a) =>
{
someCodeThatNeedsImpersonation(); // fails to "see" impersonation
}
bw.RunWorkerCompleted += (s, a) =>
{
somethingElse();
}
bw.RunWorkerAsync();
这失败了,因为显然在主线程中初始化的Impersonation
句柄未在BackgroundWorker
中使用。
当然,快速解决方法是
bw.DoWork += (s, a) =>
{
using ( new Impersonation(...) )
{
someCodeThatNeedsImpersonation(); // works, because of bw's own impersonation
}
}
但我更喜欢在每个BackgroundWorker中都不需要新的模拟句柄的解决方案(因为我肯定会忘记一个)。有没有办法分享主线程的static Impersonation
对象?
答案 0 :(得分:0)
在Windows中,为每个线程单独维护模拟标记,并且在创建新线程时不会继承模拟标记。
要走的路是模拟只需要它的代码路径,正如您已经使用using(...)
展示的那样。我要说的唯一不同之处在于,我不会发布.DoWork += { new Impersonation(...) }
,而是会做这样的事情:
var bw = new BackgroundWorker();
bw.DoWork += Impersonated(TOKEN, (s, a) => { /* code */ });
另一种方法是,BackgroundWorker
未被密封且其OnDoWork()
方法受到保护,将继承该类并覆盖OnDoWork()
以进行模拟。然后,你可以这样做:
var bw = new ImpersonatingBackgroundWorker(...)
答案 1 :(得分:0)
如blogs.msdn.com所述,将以下代码段添加到App.config
文件就足以让Impersonation
跨越线程边界。
<configuration>
<runtime>
<alwaysFlowImpersonationPolicy enabled="true"/>
<legacyImpersonationPolicy enabled="false"/>
</runtime>
</configuration>
但是,最佳实践解决方案只会在实际需要时使用模拟,而不是全局。