8

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

例如,默认应用程序域的身份是Authority\Limited(Authority 是域名或机器名)。两个插件被加载到两个子应用程序域中。加载的插件的身份是Authority\Privileged1Authority\Privileged2Authority\Privileged1Authority\Privileged2分别拥有对数据库Database1Database2的所有必要访问权限,而Authority\Limited无权访问任何上述数据库。

创建子应用程序域时,我调用System.AppDomain.SetThreadPrincipal方法传递System.Security.Principal.WindowsPrincipal实例。该实例是从System.Security.Principal.WindowsIdentity实例创建的,该实例是从重复的用户令牌创建的(请参阅http://support.microsoft.com/kb/306158)。我省略了对WindowsIdentity.Impersonate方法的调用,因为我在创建WIndowsPrincipal实例时处于默认应用程序域中。

我希望设置应用程序域线程主体足以使加载的插件成功登录到各自的数据库并执行一些 T-SQL 语句。令我惊讶的是,在打开与数据库的连接时使用了WindowsIdentity.GetCurrent()方法返回的值。该方法返回的值是进程身份或模拟身份。

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

是否可以只执行一次模拟以影响在子应用程序域中生成的所有线程?

4

1 回答 1

4

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

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

于 2011-01-29T20:19:14.820 回答