簡體   English   中英

如何在DCOM調用C#.NET 3.5服務器的同時可靠地檢查客戶端身份?

[英]How can I reliably check client identity whilst making DCOM calls to a C# .NET 3.5 Server?

我有一個舊的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()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。

有什么我做錯了嗎? 以這種方式使用模擬是否有任何警告或限制? 是否有更好或不同的方式可以讓我可靠地實現我想做的事情?

非常感謝所有的幫助。

好的,所以我采取了不同的方法,並且finall提出了一種似乎有效的方法(針對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似乎具有所需的結果,並且無論使用哪個線程來處理消息,我都能夠可靠地每次都獲得調用用戶的身份。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM