Comunicações seguras baseadas em WCF para um serviço
A segurança é um dos aspetos mais importantes da comunicação. A estrutura do aplicativo Reliable Services fornece algumas pilhas de comunicação pré-criadas e ferramentas que você pode usar para melhorar a segurança. Este artigo fala sobre como melhorar a segurança quando você está usando a comunicação remota de serviço.
Estamos usando um exemplo existente que explica como configurar uma pilha de comunicação baseada em WCF para serviços confiáveis. Para ajudar a proteger um serviço quando você estiver usando uma pilha de comunicação baseada em WCF, siga estas etapas:
Para o serviço, você precisa ajudar a proteger o ouvinte de comunicação WCF (
WcfCommunicationListener
) que você criar. Para fazer isso, 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 você precisa 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)); } }
Use
SecureWcfCommunicationClientFactory
para criar um cliente de comunicação WCF (WcfCommunicationClient
). Use 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 próxima etapa, leia API da Web com OWIN em Serviços confiáveis.