使用X509证书为Authencation启用安全功能时,未建立与服务器的连接。当客户端进行异步操作调用时,我发现此问题。以下代码适用于同步操作。例如,如果调用是使用TrainHealth而不是BeginTrainHealth,则代码可以正常工作。据我了解,安全性与操作是同步还是异步无关。 任何有关为什么这不起作用的帮助表示赞赏。
合同:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace = "http://www.bane.dk/services/fbane/2014/02/20", ConfigurationName = "Alstom.SmartBus.ESBBridge.ExternalIOPlugins.TrainData.TrainDataPort")]
public interface IStudentService
{
[System.ServiceModel.OperationContractAttribute(IsOneWay = true, AsyncPattern = false, Action = "TrainHealth")]
[System.ServiceModel.XmlSerializerFormatAttribute()]
void TrainHealth(int test);
[System.ServiceModel.OperationContractAttribute(IsOneWay = true, AsyncPattern = true, Action = "TrainHealth")]
[System.ServiceModel.XmlSerializerFormatAttribute()]
System.IAsyncResult BeginTrainHealth(int test, System.AsyncCallback callback, object asyncState);
void EndTrainHealth(System.IAsyncResult result);
}
服务器代码:
class Program
{
static void Main(string[] args)
{
ServiceHost studentServiceHost = null;
try
{
//Base Address for StudentService
Uri httpBaseAddress = new Uri("https://10.107.64.33:5060/StudentService");
//Instantiate ServiceHost
studentServiceHost = new ServiceHost(typeof(StudentService), httpBaseAddress);
CustomBinding binding = CreateBinding();
ServiceEndpoint endpoint_GD = studentServiceHost.AddServiceEndpoint(typeof(IStudentService), binding, httpBaseAddress);
//Add Endpoint to Host
studentServiceHost.AddServiceEndpoint(typeof(IStudentService), binding, httpBaseAddress + "mex");
//Metadata Exchange
ServiceMetadataBehavior serviceBehavior = new ServiceMetadataBehavior();
serviceBehavior.HttpsGetEnabled = true;
studentServiceHost.Description.Behaviors.Add(serviceBehavior);
var behavior = studentServiceHost.Description.Behaviors.Find<ServiceDebugBehavior>();
behavior.IncludeExceptionDetailInFaults = true;
studentServiceHost.Credentials.ClientCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.PeerTrust;
studentServiceHost.Credentials.ClientCertificate.Authentication.TrustedStoreLocation = StoreLocation.LocalMachine;
studentServiceHost.Credentials.ServiceCertificate.SetCertificate(System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine, System.Security.Cryptography.X509Certificates.StoreName.My, System.Security.Cryptography.X509Certificates.X509FindType.FindBySubjectName, "10.107.64.33");
ServiceSecurityAuditBehavior newAudit = new ServiceSecurityAuditBehavior();
newAudit.AuditLogLocation = AuditLogLocation.Application;
newAudit.MessageAuthenticationAuditLevel = AuditLevel.SuccessOrFailure;
newAudit.ServiceAuthorizationAuditLevel = AuditLevel.SuccessOrFailure;
newAudit.SuppressAuditFailure = false;
studentServiceHost.Description.Behaviors.Remove<ServiceSecurityAuditBehavior>();
studentServiceHost.Description.Behaviors.Add(newAudit);
studentServiceHost.Open();
Console.WriteLine("Service is live now at : {0}", httpBaseAddress);
Console.ReadKey();
}
catch (Exception ex)
{
studentServiceHost = null;
Console.WriteLine("There is an issue with StudentService" + ex.Message);
Console.ReadKey();
}
}
public static CustomBinding CreateBinding()
{
CustomBinding binding = new CustomBinding();
binding.Elements.Add(new ReliableSessionBindingElement());
TransportSecurityBindingElement sec = new TransportSecurityBindingElement();
binding.Elements.Add(sec);
binding.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap11WSAddressing10, Encoding.UTF8));
binding.Elements.Add(new HttpsTransportBindingElement()
{
RequireClientCertificate = true
});
return binding;
}
}
客户代码:
class Program
{
static ChannelFactory<IStudentService> runTrainSvcCF = null;
static IStudentService runTrainSvcProxy;
static void Main(string[] args)
{
StartClient();
}
private static void StartClient()
{
EndpointAddress endPoint = new EndpointAddress(new Uri("https://10.107.64.33:5060/StudentService"), EndpointIdentity.CreateDnsIdentity("10.107.64.34"));
CustomBinding binding = CreateBinding();
runTrainSvcCF = new ChannelFactory<IStudentService>(binding, endPoint);
System.ServiceModel.Description.ClientCredentials credentials = runTrainSvcCF.Credentials;
credentials.ClientCertificate.SetCertificate(System.Security.Cryptography.X509Certificates.StoreLocation.CurrentUser,
System.Security.Cryptography.X509Certificates.StoreName.My,
System.Security.Cryptography.X509Certificates.X509FindType.FindBySubjectName,
"10.107.64.34");
ServicePointManager.MaxServicePointIdleTime = 0;
credentials.ServiceCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.PeerTrust;
ServicePointManager.ServerCertificateValidationCallback += new System.Net.Security.RemoteCertificateValidationCallback(ValidateRemoteCertificate);
runTrainSvcProxy = runTrainSvcCF.CreateChannel();
try
{
runTrainSvcProxy.BeginTrainHealth(88, null, null);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private static bool ValidateRemoteCertificate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate cert,
System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors policyErrors)
{
return true;
}
public static CustomBinding CreateBinding()
{
CustomBinding binding = new CustomBinding();
binding.Elements.Add(new ReliableSessionBindingElement());
binding.Elements.Add(new TransportSecurityBindingElement());
binding.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap11WSAddressing10, Encoding.UTF8));
binding.Elements.Add(new HttpsTransportBindingElement()
{
RequireClientCertificate = true
});
return binding;
}
}