WindowsIdentity.Impersonate () путаница

1

У меня есть веб-приложение, размещенное IIS. он настроен с аутентификацией по форме и анонимной аутентификацией, а олицетворение включено. Учетная запись приложения - это служба сети. Анонимной учетной записью является Коста. Коста имеет доступ к базе данных. NetworkService не может получить доступ к базе данных.

Проблема заключается в том, что поток запроса (родительский поток) может обращаться к базе данных, но под поток не может.

Чтобы исправить это. Я отправляю объект идентификатора Windows основного потока в подпоток, затем я вызываю Impersonate(). "Олицетворение" означает "назначить текущий поток Windows Identity с олицетворенной учетной записью. Мой вопрос: Является ли это хорошей практикой? Существует ли риск?

\\Request thread code (Parent thread)

\\WindowsIdentity.GetCurrent() return Costa identity (impersonated)
requestFields.CurrentPrincipal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
ThreadPool.QueueUserWorkItem(LogRequest, requestFields);

-

\\ Sub thread code that works
RequestFields requestFields = (RequestFields)obj;
HttpRequest httpRequest = requestFields.Request;

var impersonationContext = ((WindowsIdentity)requestFields.CurrentPrincipal.Identity).Impersonate();
.
.
.
impersonationContext.Undo();
  • 0
    Вы не говорите, какую версию IIS вы используете. IIS7 или более поздняя версия со встроенным конвейером больше не поддерживает олицетворение непосредственно в конфигурации, главным образом из-за проблем с асинхронными запросами (т. Е. При использовании asyc / await запрос может возобновиться в другом потоке, в котором больше нет олицетворения). Так что я не уверен, что вы подразумеваете под «олицетворение включено».
Теги:
multithreading
impersonation

1 ответ

0
Лучший ответ

Причина, по которой рабочий поток не автоматически олицетворяет пользователя из потока запросов, заключается в том, что пул потоков.NET управляет созданием и повторным использованием его потоков. Если вы сами создали поток через приведенный ниже пример кода, я бы ожидал, что он автоматически наследует контекст безопасности (включая олицетворение), но вы также не будете повторно использовать потоки, которые добавили бы некоторую стоимость исполнения (см. Thread vs ThreadPool для получения более подробной информации о различиях между ними и преимуществах использования потока потока потока).

Поскольку, как вы знаете, IIS олицетворяет пользователей и согласно http://blogs.msdn.com/b/tmarq/archive/2007/07/21/asp-net-thread-usage-on-iis-7-0-and -6-0.aspx он использует пул потоков для обработки своих запросов, я бы сделал вывод о том, что нецелесообразно делать олицетворение потоков потоков потоков, пока вы предпринимаете шаги, чтобы быть как можно более уверенными, что олицетворение будет отменено даже в исключительных обстоятельствах. Если олицетворение не отменено, вы рискуете другим кодом, который использует пул потоков (ваши, другие библиотеки или сам проект.NET), назначаемый потоку, который использует некое случайное имя вместо идентификатора пула приложений.

Я не уверен, что такое класс RequestFields (быстрый поиск указывает на то, что он не является частью платформы.NET), поэтому я не понимаю, почему необходимо обернуть WindowsIdentity в WindowsPrincipal, так как вы не используйте любые свойства, отличные от Identity, и это заставляет вас использовать другой поток. Если вы владеете этим классом и можете его изменить, я бы рекомендовал изменить свойство CurrentPrincipal для непосредственного подключения к WindowsIdentity, чтобы его можно было передавать без ненужной оболочки WindowsPrincipal.

Я думаю, вам хорошо передать текущую WindowsIdentity в другой поток пула потоков и вызвать Impersonate так, как вы это делаете. Тем не менее, вы обязательно должны либо обернуть imersonationContext в используемом блоке, либо обернуть Undo в последней части блока try/finally, который начинается при вызове Impersonate, чтобы гарантировать, что олицетворение отменено даже в случае исключения или прерывания потока, Вы также должны убедиться, что копия WindowsIdentity, созданная с помощью WindowsIdentity.GetCurrent(), также удалена, поэтому все ссылки на неуправляемый токен пользователя за идентификатором закрываются детерминистически (т.е. Не завершается финализацией сборщика мусора).

Пример кода для создания нового потока:

Thread myThread = new Thread(LogRequest);

// the CLR will not wait for this thread to complete if all foreground threads
// have been terminated; this mimics the thread pool since all thread pool threads
//are designated as background threads
myThread.IsBackground = true;

myThread.Start(requestFields);

Пример кода для правильного размещения объектов WindowsImpersonationContext и WindowsIdentity с использованием блока (impersonationContext.Dispose вызовет Undo):

using (var identity = (WindowsIdentity)requestFields.CurrentPrincipal.Identity)
using (var impersonationContext = identity.Impersonate())
{
    .
    .
    .
}
  • 0
    если поток пула приложений олицетворяется, а затем завершается без вызова отмены, и этот поток используется повторно, он будет сохранять олицетворенную личность, даже если вы не вызывали олицетворение. Я могу подтвердить это с помощью некоторого кода тестирования.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню