我已经创建了一个WCF服务和一个简单的表单应用程序来访问它。到目前为止,在添加证书之前,所有的工作都很完美,我能够成功地从服务中得到一个返回。
在试验了证书之后,我已经能够更新客户端和服务中的配置,这样当从visual studio中构建时,应用程序使用证书就能完美地工作。
我的问题是,当我使用一个自托管控制台应用程序来托管visual studio以外的服务时,我得到一个 "安全通道无法打开,因为与端点的安全协商已经失败。这可能是由于在用于创建通道的EndpointAddress中没有或不正确指定EndpointIdentity。"错误。
只是想知道是否有人能看到我的配置中有任何明显的错误,可能会导致这种情况?就像我说的那样,当visual studio挂载服务时,它可以工作,但自我托管中的某些东西会导致错误。
顺便说一下:客户端跟踪只是说我上面说的错误。服务器跟踪甚至没有出现。WCFTestClient也说服务正在被托管。
干杯!
客户端。
<configuration>
<system.diagnostics>
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing"
propagateActivity="true">
<listeners>
<add name="traceListener"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="c:\Client.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="endpointCredentialsBehavior">
<clientCredentials>
<clientCertificate findValue="TraceCert"
storeLocation="LocalMachine"
x509FindType="FindBySubjectName"/>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="clientBinding">
<security>
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:8000/ContactTraceWCF" binding="wsHttpBinding"
bindingConfiguration="clientBinding" contract="ContactTraceServer.IContactTraceServer"
name="WSHttpBinding_IContactTraceWCF" behaviorConfiguration="endpointCredentialsBehavior">
<identity>
<dns value="TraceRootCA" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
服务器:
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" />
</system.web>
<system.diagnostics>
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing"
propagateActivity="true">
<listeners>
<add name="traceListener"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData= "c:\Server.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
<system.serviceModel>
<services>
<service name="ContactTraceWCF.ContactTraceServer">
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IContactTraceWCF"
contract="ContactTraceWCF.IContactTraceServer"
name="WSHttpBinding_IContactTraceWCF">
<identity>
<dns value="TraceRootCA" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/ContactTraceWCF" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True" />
<serviceCredentials>
<serviceCertificate findValue="TraceRootCA"
storeLocation="CurrentUser"
x509FindType="FindBySubjectName"/>
<clientCertificate>
<authentication certificateValidationMode="None"/>
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IContactTraceWCF">
<security mode="Message">
<message clientCredentialType="Certificate"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
</configuration>
托管控制台应用程序。
using (ServiceHost serviceHost = new ServiceHost(typeof(ContactTraceServer), new Uri("http://localhost:8000/ContactTraceWCF")))
{
try
{
serviceHost.AddServiceEndpoint(typeof(IContactTraceServer), new WSHttpBinding(), "");
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
serviceHost.Description.Behaviors.Add(smb);
serviceHost.Open();
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.ReadLine();
serviceHost.Close();
}
catch (TimeoutException timeProblem)
{
Console.WriteLine(timeProblem.Message);
Console.ReadLine();
}
catch (CommunicationException commProblem)
{
Console.WriteLine(commProblem.Message);
Console.ReadLine();
}
}
所以经过一些测试,我发现在创建自主机的时候,它并没有从WCF服务的app.config中提取,所以在构建servicehost的时候,你基本上必须重写它。
我提供了下面的代码,对我来说是可行的。
using (ServiceHost serviceHost = new ServiceHost(typeof(ContactTraceServer), new Uri("http://localhost:8000/")))
{
try
{
var binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;
serviceHost.AddServiceEndpoint(typeof(IContactTraceServer), binding, "ContactTraceWCF");
serviceHost.Credentials.ServiceCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "TraceRootCA");
serviceHost.Credentials.ClientCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None;
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
serviceHost.Description.Behaviors.Add(smb);
serviceHost.Open();
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.ReadLine();
serviceHost.Close();
}
catch (TimeoutException timeProblem)
{
Console.WriteLine(timeProblem.Message);
Console.ReadLine();
}
catch (CommunicationException commProblem)
{
Console.WriteLine(commProblem.Message);
Console.ReadLine();
} catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
}
}