Я имею дело с неприятной проблемой, которая заставила меня разорвать мои волосы. У меня есть консольное приложение C#, которое использует класс HttpListener Microsoft для прослушивания веб-запросов. Идея заключается в том, что консольное приложение запускается в фоновом режиме как UserAccountA (low priv). UserAccountB (Администратор и т. Д.) Появляется, обращается к веб-странице через слушателя и имеет свою личность. То же, что и IIS или WCF. Я считаю, что я работал над Windows 7, но теперь я нахожусь в Windows 8.1, и он снова не работает. Может быть, у меня никогда не было этого, или, может быть, это новый поворот.Как я могу убедиться, что мой уровень олицетворения Windows действителен?
Если я запускаю программу через Visual Studio, я могу получить к ней доступ с помощью Internet Explorer 11. По какой-то причине он просит указать мои локальные учетные данные. Я предполагаю, что это связано с поведением IE11. Как только я ввожу его, он принимает его. Мой код начинается так:
protected virtual void Listen(object o)
{
HttpListener h = (HttpListener)o;
while (h.IsListening && (this.Disposed == false))
{
IAsyncResult Result = null;
Result = h.BeginGetContext(new AsyncCallback(this.ListenerCallback), h);
Result.AsyncWaitHandle.WaitOne();
}
}
И подобран так (сокращенно):
protected virtual void ListenerCallback(IAsyncResult Result)
{
HttpListener h = (HttpListener)Result.AsyncState;
HttpListenerContext context = null;
System.Security.Principal.WindowsIdentity identity = null;
context = h.EndGetContext(Result);
identity = (System.Security.Principal.WindowsIdentity)context.User.Identity;
using (System.Security.Principal.WindowsImpersonationContext wic = identity.Impersonate())
{
//method call to process request, under impersonation
}
}
Я прошел через этот код при использовании двух разных счетов (один для размещения, один для доступа). Я проверял использование этого оператора:
system.security.principal.windowsidentity.getcurrent().name
То, что текущий идентификатор переходит на переход. Слушатель настроен на запуск с помощью NTLM AuthenticationScheme.
Я полагаю, что сложная часть находится в методе, который вызывается во время олицетворения. Мы делаем немного абстракции, но позвольте мне просто указать на ту часть, которая терпит неудачу. В этом случае мы подключаемся к SQL-серверу с использованием SSPI, поэтому весь смысл олицетворения заключается в том, чтобы захватить существующий вход в систему клиента и изящно получить их в SQL Server. Опять же, прямо сейчас, это все локально для одного компьютера. он даже не находится в домене активного каталога. Все локально, с локальными учетными записями. Он начинается следующим образом:
System.Data.Common.DbProviderFactory fact = null;
if (UseSql())
{
fact = System.Data.Common.DbProviderFactories.GetFactory("System.Data.SqlClient");
}
Нет ничего сложного. Мы постоянно используем фабрику поставщиков в другом проекте без каких-либо проблем (но это просто обычное приложение WPF, ничего подобного). Сразу после этого мы установили строку входа SQL с атрибутом SSPI. Но мы даже не добираемся так далеко. Это именно там, где он выходит из строя, с этим сообщением:
Первый шанс исключение типа «System.IO.FileLoadException» произошло в mscorlib.dll
Дополнительная информация: Не удалось загрузить файл или сборку 'System.Data.OracleClient, Version = 4.0.0.0, Culture = neutral, > PublicKeyToken = b77a5c561934e089' или одна из его зависимостей. Либо требуемый уровень олицетворения не был предоставлен, либо предоставленный уровень олицетворения недействителен. (Исключение из HRESULT: 0x80070542)
http://i854.photobucket.com/albums/ab103/srVincentVega/error7_zpsmb1xqrp0.png
Мы не используем Oracle вообще, я предполагаю, что это только первая вещь, которую она barfs, когда он идет и пытается открыть DbProviderFactory. Для меня ключ заключается в том, что уровень уровня олицетворения. В этом конкретном эксперименте обе учетные записи (A & B) являются локальными администраторами. Я обеспечил с помощью локальной политики безопасности, что они могут олицетворять учетные записи после входа в систему.И если я смотрю на свой журнал событий, то олицетворение DOES, похоже, работает ...
Специальные привилегии, назначенные для нового входа.
Тема: Security ID:
PC1 \ ПользовательА
Имя счета: ПользовательА
Учетная запись домена: PC1 Logon ID: 0xC4D0F3F
Привилегии:
SeSecurityPrivilege
SeTakeOwnershipPrivil EGE
SeLoadDriverPrivilege
SeBackupPrivilege
SeRestorePrivilege
SeDebugPrivilege
SeSystemEnvironmentPrivilege
SeImpersonatePrivilege
Я пробовал так много вариаций здесь, что я начинаю мешать собственному анализу. Я в основном вернулся к квадрату и не знаю, как подойти к этому. У кого-нибудь есть советы или подсказки? Кажется, это должно быть очень просто. Я не уверен, почему у меня так много проблем. Может быть, мне просто нужно отказаться от использования DbProviderFactory и пойти с OleDb или что-то еще. Но я не подтвердил, что могу загрузить любые библиотеки во время выполнения после олицетворения. Может быть, это что-то делать. Тем не менее, я был бы очень благодарен за любую помощь.
Спасибо,
Джон
Одна последняя вещь, вот Размножение шаги:
Создание дополнительного пользователя на компьютере. Войдите, чтобы создать профиль. Выйдите из системы и войдите в систему, как обычно. Запуск Visual Studio, как этого вторичного пользователя (есть несколько способов сделать это, Shift + щелкните правой кнопкой мыши на иконке VS), и внутри, сделать C# консольное приложение с этим скелетом:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
using (HttpListener h = new HttpListener())
{
h.Prefixes.Add("http://+:8090/");
h.AuthenticationSchemes = AuthenticationSchemes.Ntlm;
h.Start();
Console.WriteLine("Running");
HttpListenerContext context = h.GetContext();
System.Security.Principal.WindowsIdentity identity = null;
identity = (System.Security.Principal.WindowsIdentity)context.User.Identity;
using (System.Security.Principal.WindowsImpersonationContext wic = identity.Impersonate())
{
System.Data.Common.DbProviderFactory fact = null;
fact = System.Data.Common.DbProviderFactories.GetFactory("System.Data.SqlClient");
}
Console.ReadLine();
h.Stop();
}
}
}
}
Debug/Запуск консольное приложение. Просто вызовите Internet Explorer (ваниль, используя основную учетную запись) и получите доступ к этому URL-адресу (http://machinename:8090). Исключение происходит
http://i854.photobucket.com/albums/ab103/srVincentVega/error8_zpsilkay0bl.png
В зависимости от того, как вы это делаете, вам может потребоваться добавить локальное правило для прослушивания порта, такого как 8090. Вы можете сделать это при повышенной командной строке: ** netsh http add urlacl url = http: // +: 8090/user = (SecondaryAcctName) ** –