gpt4 book ai didi

c# - 如何在对 C# .NET 3.5 服务器进行 DCOM 调用时可靠地检查客户端身份?

转载 作者:行者123 更新时间:2023-11-30 18:09:07 26 4
gpt4 key购买 nike

我有一个旧的 Win32 C++ DCOM 服务器,我正在重写它以使用 C# .NET 3.5。客户端应用程序位于远程 Windows XP 机器上,也是用 C++ 编写的。这些客户端必须保持不变,因此我必须在新的 .NET 对象上实现接口(interface)。

这已经完成,并且在接口(interface)的实现方面正在成功地工作,并且所有调用都从旧客户端正确地进行到新的 .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() 之后,CurrentPrincipal 与该线程的初始用户匹配。

举例说明:

用户 Tom 进行由线程 1 处理的 DCOM 调用(CurrentPrincipal 正确标识 Tom)

用户 Dick 进行由线程 2 处理的 DCOM 调用(CurrentPrincipal 正确标识 Dick)

用户 Harry 进行由线程 3 处理的 DCOM 调用(CurrentPrincipal 正确标识 Harry)

用户 Bob 进行由线程 3 处理的 DCOM 调用(CurrentPrincipal 错误地将他标识为 Harry)

正如您在此图中看到的,来自客户端 Harry 和 Bob 的调用正在线程 3 上处理,并且服务器将调用客户端识别为 Harry。

我做错了什么吗?以这种方式使用模拟是否有任何注意事项或限制?有没有更好或不同的方法可以可靠地实现我想要做的事情?

我们将不胜感激。

最佳答案

好的,所以我采用了不同的方法,最终想出了一个似乎有效的方法(针对 8 个不同的远程用户进行了测试)。

我已经放弃了 Impersonation 路线,转而使用 ClientBlankets...

[DllImport("ole32.dll")]
static extern int CoQueryClientBlanket(out IntPtr pAuthnSvc, out IntPtr pAuthzSvc,
[MarshalAs(UnmanagedType.LPWStr)] out StringBuilder pServerPrincName, out IntPtr
pAuthnLevel, out IntPtr pImpLevel, out IntPtr pPrivs, out IntPtr pCapabilities);

public static string CallingUser
{
get
{
IntPtr pAthnSvc = new IntPtr();
IntPtr pAthzSvc = new IntPtr();
StringBuilder pServerPrincName = new StringBuilder();
IntPtr pAuthnLevel = new IntPtr();
IntPtr pImpLevel = new IntPtr();
IntPtr pPrivs = new IntPtr();
IntPtr pCaps = new IntPtr(4);
string sCallingUser = string.Empty;

try
{
CoQueryClientBlanket(out pAthnSvc,
out pAthzSvc,
out pServerPrincName,
out pAuthnLevel,
out pImpLevel,
out pPrivs,
out pCaps);
}
catch (Exception ex)
{
Logger.Write(ex.Message);
}
finally
{
sCallingUser = System.Runtime.InteropServices.Marshal.PtrToStringAuto(pPrivs);
}

return sCallingUser;
}
}

使用 CoCreateClientBlanket 似乎有预期的结果,而且我每次都能可靠地获得调用用户的身份,无论使用哪个线程处理消息。

关于c# - 如何在对 C# .NET 3.5 服务器进行 DCOM 调用时可靠地检查客户端身份?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2674637/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com