我有一个旧的 Win32 C++ DCOM 服务器,我正在重写它以使用 C# .NET 3.5。客户端应用程序位于远程 Windows XP 计算机上,也是用 C++ 编写的。这些客户端必须保持不变,因此我必须在新的 .NET 对象上实现接口。
这已经完成,并且在接口的实现方面正在成功工作,并且从旧客户端到新 .NET 对象的所有调用都正确进行。
但是,我在从 DCOM 客户端获取调用用户的身份时遇到问题。为了尝试识别发起 DCOM 调用的用户,我在服务器上有以下代码......
[DllImport("ole32.dll")]
static extern int CoImpersonateClient();
[DllImport("ole32.dll")]
static extern int CoRevertToSelf();
private string CallingUser
{
get
{
string sCallingUser = null;
if (CoImpersonateClient() == 0)
{
WindowsPrincipal wp = System.Threading.Thread.CurrentPrincipal as WindowsPrincipal;
if (wp != null)
{
WindowsIdentity wi = wp.Identity as WindowsIdentity;
if (wi != null && !string.IsNullOrEmpty(wi.Name))
sCallingUser = wi.Name;
}
if (CoRevertToSelf() != 0)
ReportWin32Error("CoRevertToSelf");
}
else
ReportWin32Error("CoImpersonateClient");
return sCallingUser;
}
}
private static void ReportWin32Error(string sFailingCall)
{
Win32Exception ex = new Win32Exception();
Logger.Write("Call to " + sFailingCall + " FAILED: " + ex.Message);
}
当我得到CallingUser
属性,前几次返回的值是正确的,并且识别出正确的用户名,但是,在 3 或 4 个不同的用户成功拨打电话后(并且情况各不相同,所以我无法更具体),更多的用户似乎被识别为之前拨打过电话的用户。
我注意到,前几个用户的 DCOM 调用在自己的线程上处理(即,来自特定客户端的所有调用都由单个唯一线程处理),然后后续用户由与以下相同的线程处理早期的用户,以及调用后CoImpersonateClient()
, the CurrentPrincipal
与该线程的初始用户匹配。
为了显示:
用户 Tom 进行由线程 1 处理的 DCOM 调用(CurrentPrincipal
正确识别汤姆)
用户 Dick 进行由线程 2 处理的 DCOM 调用(CurrentPrincipal
正确识别迪克)
用户 Harry 进行由线程 3 处理的 DCOM 调用(CurrentPrincipal
正确识别哈利)
用户 Bob 进行 DCOM 调用,该调用由线程 3 处理(CurrentPrincipal
错误地将他识别为哈利)
正如您在此图中所看到的,来自客户端 Harry 和 Bob 的调用正在线程 3 上处理,并且服务器将调用客户端识别为 Harry。
我做错了什么吗?
以这种方式使用模拟有任何警告或限制吗?
有没有更好或不同的方式可以可靠地实现我想要做的事情?
我们将不胜感激所有帮助。