#multithreading #wcf #iis
#многопоточность #wcf #iis
Вопрос:
У меня есть набор служб WCF, настроенных с использованием wsHttpBinding с IIS, и я внедрил пользовательскую безопасность (с использованием заголовков сообщений) для определения пользователя, который делает запрос. Я всегда понимал, основываясь на нескольких годах опыта NetTcpBinding (используя службу Windows для размещения, а не IIS), что каждый запрос, полученный конечной точкой WCF, попадает в новый поток. Используя это предположение, мой пользовательский класс безопасности (который реализует IDispatchMessageInspector) устанавливает идентификатор потока на основе нахождения «токена» (идентификатора Guid) в заголовке сообщения следующим образом:
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel, InstanceContext instanceContext)
{
string token = string.Empty;
if (request.Headers.FindHeader("SecurityToken", Primitives.SerializationNamespace) > -1)
token = request.Headers.GetHeader<string>("SecurityToken", Primitives.SerializationNamespace);
if (!string.IsNullOrEmpty(token))
Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(token, "AppName"), new string[] { "testrole" });
else
Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity("guest", "AppName"), new string[] { });
}
return null;
}
Однако при тестировании этого, и несмотря на то, что моя внутренняя переменная (которая содержит объект user) помечена как ThreadStatic, новые запросы, похоже, сохраняют идентификатор предыдущего вызывающего абонента.
Вот пример:
[ThreadStatic]
private static User _CurrentUser = null;
internal static User CurrentUser
{
get
{
//this holds the value of the previous caller's identity still, even though the
//thread's Identity.Name is now equal to the new caller's Guid
if (_CurrentUser == null)
_CurrentUser = UserData.GetByToken(Thread.CurrentPrincipal.Identity.Name);
return _CurrentUser;
}
}
Я также попытался пометить все реализации моей службы (непосредственно за файлом .svc) следующим атрибутом, но это ничего не изменило:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
Любые идеи о том, как я могу гарантировать, что каждый запрос находится в новом потоке? Или есть лучший способ сохранить / определить, кто пользователь, отправляющий запрос, без какого-либо возможного перекрытия?
Комментарии:
1. С какой стати ты играешь
ThreadStatic
? Чего вы пытаетесь достичь?
Ответ №1:
Использование ThreadStatic
переменной в среде, где у вас нет потоков под вашим контролем, — это путь к катастрофе. Как WCF (IIS и автономный), так и ASP.NET внутренне использовать пул потоков = каждый запрос обслуживается отдельным потоком, но эти потоки повторно используются для последующих запросов, и избежать этого невозможно.
Используйте пользовательское OperationContext
расширение для хранения вашего пользователя вместо ThreadStatic
переменной.
Комментарии:
1. Я думаю, что это именно то, что мне было нужно. Я протестирую немного больше, но, похоже, он работает отлично. Спасибо!