保護服務的 WCF 通訊
安全性是通訊最為重視的其中一個部分。 Reliable Services 應用程式架構會提供可用來改善安全性的一些預先建置通訊堆疊和工具。 本文探討如何改善使用服務遠端作業時的安全性。
我們將使用現有範例說明如何設定 Reliable Services 的 WCF 通訊堆疊。 若要協助保護使用 WCF 通訊堆疊時的服務安全,請遵循下列步驟 ︰
對於此服務,您需要協助保護所建立之 WCF 通訊接聽程式的安全 (
WcfCommunicationListener
)。 若要這樣做,請修改CreateServiceReplicaListeners
方法。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; }
在用戶端,於先前範例中建立的
WcfCommunicationClient
類別會保持不變。 但是,您需要覆寫WcfCommunicationClientFactory
的CreateClientAsync
方法: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)); } }
使用
SecureWcfCommunicationClientFactory
來建立 WCF 通訊用戶端 (WcfCommunicationClient
)。 使用用戶端來叫用服務方法。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;