sen

导航

学习笔记之 WCF安全(1) SSL安全,无客户端验证(wsHttpBinding)

Posted on 2009-11-22 23:15  sen  阅读(3057)  评论(1)    收藏  举报

说明 :很多东西引用自老徐的博客

请注意下面这一部门是以后学习WCF安全的基础

一,制作证书

前面讲过一个在于数字证书的,它要用的是一个证书服务器去颁发证书 ,这里用的是一个制作证书的工具 makecert.exe

请注意:不要用这个路径下面的C:\Program Files\Microsoft Visual Studio 9.0\SmartDevices\SDK\SDKTools

而要用C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin 路径下面的makecert.exe 为了方便把makecert.exe 拷到了H:\cer下面

制作证书 打开CMD 如下图执行

makecert -sr localmachine -ss My -n CN=WCFServerPK -sky exchange -pe -r

image

此时打MMC,添加一个证书控制台,会看到如下的界面面,(123和上图的123相对应)

image image

此时的证书是未信任的(看上面右图的那个XX),要把证书添加到受信任根证书颁发机构,这个证书就被信任了! 

有两种方法:1,选中证书右键复制 ,到受信任根证书颁发机构的证书目录里执行粘贴(那个右图的那个XX就会消失)

2,通过导出带私钥的证书(请记住要输入的密码),然后再导入到受信任根证书颁发机构的证书目录里,效果同上

一,SSL证书设置

在这里先讲一下HttpCfg.exe / Netsh.exe  (为使用的端口SSL注册证书)

Windows Server 2003 或 Windows XP,则使用 HttpCfg.exe 工具。Windows Server 2003 中已安装该工具。下载该工具/Files/frank_xl/HttpcfgFrankXuLei.rar。如果运行的是 Windows Vista,则使用已安装的 Netsh.exe 工具。在Windows\System32目录下。

查询SSL端口证书设置信息:netsh http show sslcert(XP:httpcfg query ssl) 显示如下图(有一个SSL证书):

image

把这个证书删除:netsh http delete  sslcert 192.168.85.1:99

(XP:httpcfg delete ssl –i 192.168.85.1:99 -h 9174185b2860b6d5ec3de133d5fcc4e1419b09e5)

image

制作SSL证书:netsh http add sslcert ipport=192.168.85.1:99 certhash=8b59064d68ca711670b3c350b2c8eb7bafec27cf  appid={00112233-8899-6677-1122-AABBCCEEDDFF}

其中8b59064d68ca711670b3c350b2c8eb7bafec27cf为证书的指纹(证书指纹把中间的空格去掉,请注意如果指纺前面有空间或者tab,也请去掉),{00112233-8899-6677-1122-AABBCCEEDDFF}为任意串

(XP:httpcfg set ssl -i 192.168.85.1:99 -h 8b59064d68ca711670b3c350b2c8eb7bafec27cf)

image image

请注意下面这一部门是以后学习WCF安全的基础

下面开始讲WCF相关的安全知识(有关WCF的基础请看我写的WCF基础这一篇)

通过上面的配置后,开始做后面的操作

一,新建立一个WCF Service Libary ,如下图  ,默认会有一个App.config(配置文件) ,IService1.cs(接口),Service1.cs(实现)

image 

改IService1.cs改成如下:

namespace WCF
{
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        string GetData(string  value);
    }
      
}

改Service1.cs:

namespace WCF
{
    public class Service1 : IService1
    {
        public string GetData(string  value)
        {
            return string.Format("WCF Server Return :", value);
        }

    }
}

二,新加一个WCF 宿主:(ConsoleApplication命名为:WCFHost)

把WCF工程里的App.config(配置文件)复制到这个工程中,做如下说明的修改

<?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.85.1:99/" /> <!--把baseAddress 改成那个SSL证书的地址+端口-->
          </baseAddresses>
        </host>
        <endpoint address ="myWCF" binding="wsHttpBinding" contract="WCF.IService1"  bindingConfiguration  ="mybehaviorConfiguration">
          <!--加address ="myWCF" /  bindingConfiguration  ="mybehaviorConfiguration" 处下面的配置来对应-->
          <!-- 删除下面的结点->
          <!--<identity>
            <dns value="localhost"/>
          </identity>-->
        </endpoint>
        <!--<endpoint address="mex" binding="mexHttpBinding" 改为 mexHttpsBinding   contract="IMetadataExchange"/>-->
        <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="WCF.Service1Behavior">
          <serviceMetadata httpsGetEnabled = "True"/> <!-- 把 httpGetEnabled  改为 httpsGetEnabled -->
          <serviceDebug includeExceptionDetailInFaults="False" />
          <!--指定下面服务器证书 开始-->
          <serviceCredentials >
            <!--和那个新加证书相对应的-->
            <serviceCertificate  storeName="My"  x509FindType="FindBySubjectName" findValue="WCFServerPK" storeLocation="LocalMachine"/>
          </serviceCredentials>
          <!--指定下面服务器证书 结束-->
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <!--  加上下面的bindings 配置结点 开始 -->
    <bindings >
      <wsHttpBinding >
        <binding  name ="mybehaviorConfiguration">
          <security mode ="Transport">
            <transport clientCredentialType="None"/><!-- 客户端验证为空 -->
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <!-- 加上下面的bindings 配置结点 结束-->
  </system.serviceModel>
</configuration>

把System.ServiceModel和前面的那个WCF引用进来,在main 函数里打开WCF服务监听

namespace WCFHost
{
    class Program
    {
        static void Main(string[] args)
        {
            using (System.ServiceModel.ServiceHost Host = new System.ServiceModel.ServiceHost(typeof(WCF.Service1)))
            {
                if (Host.State != System.ServiceModel.CommunicationState.Opened)
                    Host.Open();
                Console.Write("WCF SSL 服务打开!!!");
                Console.Read();

            }
        }
    }
}

这时候运行WCFHost 就可以打开服务监听

三,新加一个客户端 (ConsoleApplication命名为:WCFClient)

1,编译刚才的WCFHost , 运行bin目录下的WCFHost.exe 

2,返回WCFClient 工程 ,右键加一个Add service Reference

在地址栏输入https://192.168.85.1:99/ 或者 https://192.168.85.1:99/mex  前面这部分https://192.168.85.1:99 是SSL证书的地址,要一致,mex 是一个描述服务

如下图,按yes 后输入WCFClient点OK就加入了引用

image

不知道下面这种为什么不行? (在地址栏输入https://192.168.85.1:99/myWCF   这种却不行!!!!)如下图image

3,加进System.Net 引用

客户代码如下:(请注意重写证验证的那部分方法)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;/////////////////
using System.Net.Security;///////////////
using System.Security.Cryptography.X509Certificates;//加上X509证书命名空间

namespace WCFClient
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                WCFServer.Service1Client wcfClient = new WCFClient.WCFServer.Service1Client();
                string strReturn = "send to server String !!";
                //这下面这一步非常关键,它重写了服务器的验证方法,即不要验证,直接发送请求到服务器端
                //重写验证服务端证书的方法。
                System.Net.ServicePointManager.ServerCertificateValidationCallback  += MyCertificateValidate;
                strReturn = wcfClient.GetData(strReturn );
                Console.Write(strReturn);
                Console.Read();
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception : {0}", e.Message);
            }
            Console.WriteLine("Press any key to exit");
            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;
        }
    }

}

 

至此一个SSL安全的WCF就算完成了,在这里没有了客户端的验证过程 ,这个以后的内容中将会讲到