Простое изменение защиты с Нет на Транспорт не должно влиять на приложение, запущенное через Authenticate_Request. Возможно, вам следует присоединить отладчик к реализации сервиса и посмотреть, что такое HttpContext.Current.User. Это ваш пользовательский принципал или он тоже не установлен? Вы также можете добавить туда пару сообщений Debug.Write и посмотреть, каков порядок операций. Происходит ли событие Authenticate_Request после того, как вы ожидаете его?
Возможно, вы столкнулись с этой проблемой из MS Connect , если вы используете <serviceAuthorization principalPermissionMode="UseAspNetRoles" />
в своей конфигурации - похоже, этот параметр не совместим с защищенным транспортом, и WCF переопределяет принципала. Если вы устанавливаете принципал, похоже, вам нужно использовать principalPermissionMode="None"
для этого.
Убедитесь, что у вас по-прежнему включен Режим совместимости ASP.NET в службе либо через config (<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
), либо через атрибуты службы ([AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
). Без этого у службы не будет доступа к HttpContext.Current.
Кроме того, вместо получения HttpContext.Current.User в конструкторе реализации службы, попробуйте переместить его в поведение, которое вы присоединяете к службе. Реализуйте IDispatchMessageInspector
, который обрабатывает событие AfterReceiveRequest
и передает принципала из веб-контекста в поток. Это будет выглядеть примерно так:
public class HttpContextPrincipalInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
if (HttpContext.Current != null)
{
IPrincipal principal = HttpContext.Current.User;
Thread.CurrentPrincipal = principal;
}
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState) { }
}
И, конечно, реализовать IEndpointBehavior
для подключения диспетчера ...
public class HttpContextPrincipalBehavior : IEndpointBehavior
{
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
ChannelDispatcher channelDispatcher = endpointDispatcher.ChannelDispatcher;
foreach (EndpointDispatcher endpointDispatch in channelDispatcher.Endpoints)
{
endpointDispatch.DispatchRuntime.MessageInspectors.Add(new HttpContextPrincipalInspector());
}
}
// AddBindingParameters, ApplyClientBehavior, and Validate implementations
// can be empty - they don't do anything.
}
... и пользовательский BehaviorExtensionElement
, чтобы вы могли использовать его в конфигурации WCF:
public class HttpContextPrincipalElement : BehaviorExtensionElement
{
public override Type BehaviorType
{
get { return typeof(HttpContextPrincipalBehavior); }
}
protected override object CreateBehavior()
{
return new HttpContextPrincipalBehavior();
}
}
Затем вы можете сконфигурировать любую из ваших служб, чтобы использовать это как поведение конечной точки, чтобы реализация службы напрямую не общалась с веб-контекстом. Это немного облегчает тестирование и может полностью решить проблему - каждый раз, когда приходит сообщение для службы, оно автоматически передает основную часть, а не полагается на создание службы.