sen

导航

学习笔记之 WCF安全(5) 数字证书+ 客户端证书验证(wshttpBinding)

Posted on 2009-11-19 21:33  sen  阅读(1448)  评论(2)    收藏  举报

为了更好都做这个实验, 我用了一台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  然后做如下修改

<?xml version="1.0" encoding="utf-8" ?>
<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的客户端口测试做完了!

关键的一步就是要把证书让服务器信任!

<?xml version="1.0" encoding="utf-8" ?>
<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>