Proteger comunicações baseadas em WCF para um serviço
A segurança é um dos aspetos mais importantes da comunicação. A arquitetura da aplicação Reliable Services fornece algumas pilhas e ferramentas de comunicação pré-criadas que pode utilizar para melhorar a segurança. Este artigo aborda como melhorar a segurança quando está a utilizar a comunicação remota do serviço.
Estamos a utilizar um exemplo existente que explica como configurar uma pilha de comunicação baseada em WCF para serviços fiáveis. Para ajudar a proteger um serviço quando estiver a utilizar uma pilha de comunicação baseada em WCF, siga estes passos:
Para o serviço, tem de ajudar a proteger o serviço de escuta de comunicação do WCF (
WcfCommunicationListener
) que criar. Para tal, modifique oCreateServiceReplicaListeners
método .protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners() { return new[] { new ServiceReplicaListener( this.CreateWcfCommunicationListener) }; } private WcfCommunicationListener<ICalculator> CreateWcfCommunicationListener(StatefulServiceContext context) { var wcfCommunicationListener = new WcfCommunicationListener<ICalculator>( serviceContext:context, wcfServiceObject:this, // For this example, we will be using NetTcpBinding. listenerBinding: GetNetTcpBinding(), endpointResourceName:"WcfServiceEndpoint"); // Add certificate details in the ServiceHost credentials. wcfCommunicationListener.ServiceHost.Credentials.ServiceCertificate.SetCertificate( StoreLocation.LocalMachine, StoreName.My, X509FindType.FindByThumbprint, "9DC906B169DC4FAFFD1697AC781E806790749D2F"); return wcfCommunicationListener; } private static NetTcpBinding GetNetTcpBinding() { NetTcpBinding b = new NetTcpBinding(SecurityMode.TransportWithMessageCredential); b.Security.Message.ClientCredentialType = MessageCredentialType.Certificate; return b; }
No cliente, a
WcfCommunicationClient
classe que foi criada no exemplo anterior permanece inalterada. Mas tem de substituir oCreateClientAsync
método deWcfCommunicationClientFactory
:public class SecureWcfCommunicationClientFactory<TServiceContract> : WcfCommunicationClientFactory<TServiceContract> where TServiceContract : class { private readonly Binding clientBinding; private readonly object callbackObject; public SecureWcfCommunicationClientFactory( Binding clientBinding, IEnumerable<IExceptionHandler> exceptionHandlers = null, IServicePartitionResolver servicePartitionResolver = null, string traceId = null, object callback = null) : base(clientBinding, exceptionHandlers, servicePartitionResolver,traceId,callback) { this.clientBinding = clientBinding; this.callbackObject = callback; } protected override Task<WcfCommunicationClient<TServiceContract>> CreateClientAsync(string endpoint, CancellationToken cancellationToken) { var endpointAddress = new EndpointAddress(new Uri(endpoint)); ChannelFactory<TServiceContract> channelFactory; if (this.callbackObject != null) { channelFactory = new DuplexChannelFactory<TServiceContract>( this.callbackObject, this.clientBinding, endpointAddress); } else { channelFactory = new ChannelFactory<TServiceContract>(this.clientBinding, endpointAddress); } // Add certificate details to the ChannelFactory credentials. // These credentials will be used by the clients created by // SecureWcfCommunicationClientFactory. channelFactory.Credentials.ClientCertificate.SetCertificate( StoreLocation.LocalMachine, StoreName.My, X509FindType.FindByThumbprint, "9DC906B169DC4FAFFD1697AC781E806790749D2F"); var channel = channelFactory.CreateChannel(); var clientChannel = ((IClientChannel)channel); clientChannel.OperationTimeout = this.clientBinding.ReceiveTimeout; return Task.FromResult(this.CreateWcfCommunicationClient(channel)); } }
Utilize
SecureWcfCommunicationClientFactory
para criar um cliente de comunicação WCF (WcfCommunicationClient
). Utilize o cliente para invocar métodos de serviço.IServicePartitionResolver partitionResolver = ServicePartitionResolver.GetDefault(); var wcfClientFactory = new SecureWcfCommunicationClientFactory<ICalculator>(clientBinding: GetNetTcpBinding(), servicePartitionResolver: partitionResolver); var calculatorServiceCommunicationClient = new WcfCommunicationClient( wcfClientFactory, ServiceUri, ServicePartitionKey.Singleton); var result = calculatorServiceCommunicationClient.InvokeWithRetryAsync( client => client.Channel.Add(2, 3)).Result;
Como passo seguinte, leia API Web com OWIN no Reliable Services.