У меня есть старый Win32 C ++ DCOM Server, который я переписываю для использования 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
совпадает с исходным пользователем этого потока.
Для иллюстрации:
Пользователь Том делает вызовы DCOM, которые обрабатываются потоком 1 (CurrentPrincipal
правильно идентифицирует Тома)
Пользователь Дик делает вызовы DCOM, которые обрабатываются потоком 2 (CurrentPrincipal
правильно идентифицирует Дика)
Пользователь Harry делает вызовы DCOM, которые обрабатываются потоком 3 (CurrentPrincipal
правильно идентифицирует Гарри)
Пользователь Боб делает вызовы DCOM, которые обрабатываются потоком 3 (CurrentPrincipal
неправильно идентифицирует его как Гарри)
Как вы можете видеть на этом рисунке, вызовы клиентов Гарри и Боба обрабатываются в потоке 3, и сервер идентифицирует вызывающего клиента как Гарри.
Есть ли что-то, что я делаю не так?
Существуют ли какие-либо предостережения или ограничения на использование Олицетворения таким образом?
Есть ли лучший или иной способ, которым я могу НАДЕЖНО добиться того, что я пытаюсь сделать?
Любая помощь будет принята с благодарностью.