Res*_*ing 8 c# impersonation identity appdomain principal
我正在开发一个需要将插件加载到单独的子应用程序域中的应用程序.只有一个插件加载到一个子应用程序域中.每个插件都需要不同的Windows标识,并且这些标识与默认(父)应用程序域中使用的Windows标识不同.每个插件都加载一个或多个子插件.
例如,默认应用程序域的身份是Authority\Limited(权限是域名或计算机名称).两个插件加载到两个子应用程序域中.加载的插件的标识是Authority\Privileged1和Authority\Privileged2.Authority\Privileged1和Authority\Privileged2分别具有对数据库Database1和Database2的所有必要访问权限,而Authority\Limited无权访问任何上述数据库.
在创建子应用程序域时,我调用System.AppDomain.SetThreadPrincipal方法传递System.Security.Principal.WindowsPrincipal实例.该实例是从从重复的用户令牌创建的System.Security.Principal.WindowsIdentity实例创建的(请参阅http://support.microsoft.com/kb/306158).我已经省略了对WindowsIdentity.Impersonate方法的调用,因为我在创建WIndowsPrincipal实例时处于默认应用程序域中.
我希望设置app域线程主体足以使加载的插件成功登录到各自的数据库并执行一些T-SQL语句.令我惊讶的是,打开与数据库的连接时使用WindowsIdentity.GetCurrent()方法返回的值.方法返回的值是进程标识或模拟标识.
由于进程标识没有使用数据库所必需的权限,因此不可接受.因此,冒充必须发挥作用.但是,模拟必须仅在子应用程序域中进行.每个插件都公开了用于执行插件加载和卸载的方法.我知道我必须在开始时进行模拟并撤消这些方法结束时的模拟.但是,必须对子应用程序域中生成的所有线程进行模拟.由于每个插件都加载了一个或多个子插件,并且每个插件可能会产生一个或多个线程,因此必须在许多地方执行模拟,这看起来非常混乱.
是否可以仅执行一次模拟,以便影响在子应用程序域中生成的所有线程?
不,你不能这样做 - 模拟是针对每个线程的,同一线程可以在调用堆栈上拥有来自多个 AppDomain 的代码。对于插件系统尤其如此,其中主代码(来自某些主应用程序域)在单独的应用程序域中调用插件的逻辑。
本质上,您必须在调用插件之前进行模拟,并在完成后恢复。请注意,如果插件使用线程池进行自己的操作,则需要正确模拟。