为了更好都做这个实验, 我用了一台VM做客户端,只有两台机才能真正的看出效果 !
主机:192.168.172.1 //客户机192.168.721.230
主机的证书环境和前面几讲一样(因为原来的源码没了,我重新做了一个解决方案)
首先配置主机的配置文件,让只有有证书的客户端才能访问
一般地 behavior 下面设置的是为了让对方验证自己的,而bindings下面的要求对方提供什么来证明自己的身份
主机的C#代码还是和原来一样!
下面一步是关键的一步
在客户端中用 makecert -sr localmachine -ss My -n CN=WCFClientPK -sky exchange -pe –r
建立客户端证书 (这个建立在个人证书下面, 经测试没有必要把把放到可信任的机构中去! )
把证书导出,请选择不要导出私钥, 假设假出文件名为Client.cer
对Client.cer复制到主机上,且把它导入到个人,还可信任的CA中去(这有点自欺欺人,哈哈!)
然后配置客户 ,按前几课讲的方法 更新一个 service reference 然后做如下修改
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IService1" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Transport">
<transport clientCredentialType="Certificate" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true"
establishSecurityContext="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://192.168.172.1:99/myWCF" binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IService1" contract="WCFHost.IService1"
name="WSHttpBinding_IService1" behaviorConfiguration="MyClientBehavior"/>
</client>
<!--这里加上要传到主机上进行验证的证书 ,可以直接用证书文件-->
<behaviors >
<endpointBehaviors >
<behavior name ="MyClientBehavior">
<clientCredentials>
<clientCertificate storeName="My"
x509FindType="FindBySubjectName"
findValue="WCFClientPK"
storeLocation="LocalMachine"/>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
客户端的C#代码没什么改变
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
namespace WCFClient
{
class Program
{
static void Main(string[] args)
{
WCFHost.Service1Client client = new WCFClient.WCFHost.Service1Client();
//client.ClientCredentials.UserName.UserName = "Asen";
//client.ClientCredentials.UserName.Password = "Asen";
//为什么这里把服务器的证书导到客户端,这个信任还是不存在呢?
System.Net.ServicePointManager.ServerCertificateValidationCallback += myCertificateValidate;
Console.Write(client.GetData("客戶端傳過去的值!"));
Console.Read();
}
private static bool myCertificateValidate( object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error)
{
// trust any certificate!!!
System.Console.WriteLine("Warning, trust any certificate");
return true;
}
}
}
至此一个通过证书来访问WCF的客户端口测试做完了!
关键的一步就是要把证书让服务器信任!
<configuration>
<system.web>
<compilation debug="true" />
</system.web>
<system.serviceModel>
<services>
<service name="WCF.Service1" behaviorConfiguration="WCF.Service1Behavior"><!--指定配置-->
<host>
<baseAddresses>
<add baseAddress = "https://192.168.172.1:99/" />
</baseAddresses>
</host>
<endpoint address ="myWCF" binding="wsHttpBinding" contract="WCF.IService1" bindingConfiguration="mywsHttpBindings">
</endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WCF.Service1Behavior">
<serviceMetadata httpsGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
<!--下面添加服务器证书 这一部分加了有什么用,现在还不清楚 ,原以为是为了让客户信任的,结果把服务器证书导到客户端,结果还是强制信任-->
<serviceCredentials>
<serviceCertificate storeName="My" x509FindType="FindBySubjectName" findValue="WCFServerPK" storeLocation="LocalMachine"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding><!--这里还是wsHttpBinding-->
<binding name ="mywsHttpBindings" >
<security mode ="Transport">
<transport clientCredentialType ="Certificate"/><!--************把验证方式由原来第一讲的无验证改为证书验证-->
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
</configuration>