应用程序域级别模拟

时间:2011-01-29 14:07:00

标签: c# identity appdomain impersonation principal

我正在开发一个需要将插件加载到单独的子应用程序域中的应用程序。只有一个插件加载到一个子应用程序域中。每个插件都需要不同的Windows标识,并且这些标识与默认(父)应用程序域中使用的Windows标识不同。每个插件都会加载一个或多个子插件。

E.g。默认应用程序域的标识是 Authority \ Limited (权限是域名或计算机名称)。两个插件加载到两个子应用程序域中。加载的插件的标识是 Authority \ Privileged1 Authority \ Privileged2 Authority \ Privileged1 Authority \ Privileged2 分别拥有对数据库 Database1 Database2 的所有必要访问权限,而< em> 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()方法返回的值。方法返回的值是进程标识或模拟标识。

由于进程标识没有使用数据库所必需的权限,因此不可接受。因此,冒充必须发挥作用。但是,模拟必须仅在子应用程序域中进行。 每个插件都公开了用于执行插件加载和卸载的方法。我知道我必须在开始时进行模拟并撤消这些方法结束时的模拟。 但是,必须对子应用程序域中生成的所有线程进行模拟。由于每个插件加载一个或多个子插件,并且每个插件可能会产生一个或多个线程,因此必须在许多地方执行模拟,这看起来非常混乱。

是否可以仅执行模拟,以便影响在子应用域中生成的所有线程?

1 个答案:

答案 0 :(得分:3)

不,你不能这样做 - 每个线程都有模拟,同一个线程可以在调用堆栈上拥有来自多个AppDomain的代码。对于插件系统尤其如此,其中主代码(来自某些主AppDomain)在单独的AppDomain中调用插件的逻辑。

基本上你必须在调用插件之前进行模拟,并在完成后恢复。请注意,如果插件使用threadpool进行自己的操作,则需要正确模拟。