x.509证书在WCF中的应用

本文介绍如何在WCF中使用X.509证书实现安全通信,包括证书生成、服务端配置及客户端调用过程。

为什么要用x.509证书?

WCF的服务端和客户端之间,如果不作任何安全处理(即服务端的<security mode="None">),则所有传输的消息将以明文方式满天飞,在internet/intranet环境下无疑是很不安全的,这就是用证书的目的。(当然WCF还有其它安全机制,比如最常见的UserName方式,但通常每次都要从数据库读取用户名/密码信息进行验证,比较麻烦,开销也大,个人觉得还是证书最为方便)--关于x.509证书

的基本知识,可参见http://www.cnblogs.com/yjmyzz/archive/2008/08/19/1271171.html

大致原理(个人理解,可能不太准确):

正确设置服务端与客户端证书后,WCF的服务端启动时,需要利用服务端证书验证,如果验证通过将正常启动,否则报异常,同时客户端调用服务端方法时,也需要提供客户端证书,服务端接受到客户端证书后,验证客户端证书的有效性,如果通过,则允许客户端正常调用。

下面将逐步讲解如何使用:

1.制作证书

先进入到vs2008的命令行状态,即:

开始-->程序-->Microsoft Visual Studio 2008-->Visual Studio Tools-->Visual Studio 2008 命令提示

键入:

makecert -r -pe -n "CN=MyServer" -ss My -sky exchange

解释一下:makecert.exe是一个专门用来制作证书的小工具,上面一行的意思就是制作一个CN=MyServer的服务器证书,默认存储在CurrentUser\My这个位置,同时这个证书标识为可导出。(详细的

MakeCert参数可参见http://msdn.microsoft.com/zh-cn/bfsktky3(vs.80).aspx)

再输入:

makecert -r -pe -n "CN=MyClient" -ss My -sky exchange

生成客户端证书,证书生成好以后,可以在IE里查看到,IE-->工具-->Internet选项-->内容-->证书

x.509证书在WCF中的应用 - qiuguangchun - sandea的个人主页

同时如何管理已经安装的证书,可参见http://www.cnblogs.com/yjmyzz/archive/2008/08/20/1272128.html

2.wcf服务端

vs.net2008启动后,新建一个控制台应用程序-->(右击)添加-->新建项-->WCF服务-->命名为MyService.cs-->保存

保存后,系统会自动生成一个接口文件IMyService.cs

二个文件的内容如下:

IMyService.cs

using System;  

using System.ServiceModel;

namespace Server

{

    // 注意: 如果更改此处的接口名称 "IMyService",也必须更新 App.config 中对 "IMyService" 的引用。

     [ServiceContract]

    public interface IMyService

     {

         [OperationContract]

        string Test();

     }

}

MyService.cs

using System;

using System.ServiceModel;

namespace Server

{

    // 注意: 如果更改此处的类名 "MyService",也必须更新 App.config 中对 "MyService" 的引用。

    public class MyService : IMyService

     {

        public string Test()

         {

             Console.WriteLine("服务端输出:\n" + ServiceSecurityContext.Current.PrimaryIdentity.AuthenticationType);

             Console.WriteLine(ServiceSecurityContext.Current.PrimaryIdentity.Name);

            return "服务端时间:" + DateTime.Now.ToString();

         }

     }

}

再来新建一个cs文件:CustomX509CertificateValidator.cs

内容先贴在下面

using System;

using System.Security.Cryptography.X509Certificates;

using System.IdentityModel.Tokens;

using System.IdentityModel.Selectors;

namespace Server

{

    public class CustomX509CertificateValidator : X509CertificateValidator

     {

        public override void Validate(X509Certificate2 certificate)

         {

             Console.WriteLine(certificate.Subject);

             Console.WriteLine(certificate.Thumbprint);

            if (certificate.Thumbprint != "3E4D4B64A90810B6CFF9B1DD2390D8C9488747BF")

                throw new SecurityTokenException("Certificate Validation Error!");

         }

     }

}

注意:项目必须先添加对System.IdentityModel的引用

解释一下:

这个文件的用户是:客户端要调用服务端方法,并提供客户端证书时,用来验证客户端证书的有效性。注意里面的if (certificate.Thumbprint != "3E4D4B64A90810B6CFF9B1DD2390D8C9488747BF")这一句,大家调试的时候,里面的3E4D4B64A90810B6CFF9B1DD2390D8C9488747BF要换成你自己的客户端证书的信息(每一个证书对应的这一串字符都是唯一的),可通过在IE浏览器里,查看MyClient证书的详细信息得到,见下图:

x.509证书在WCF中的应用 - qiuguangchun - sandea的个人主页

同时注意配置文件App.Config,内容如下

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

    <system.serviceModel>

        <behaviors>

            <serviceBehaviors>

                <behavior name="Server.MyServiceBehavior">

                  <serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:8080" />

                  <serviceDebug includeExceptionDetailInFaults="true" />

                  <serviceCredentials>

                    <clientCertificate>

                      <authentication certificateValidationMode="Custom" customCertificateValidatorType="Server.CustomX509CertificateValidator,Server"/>

                    </clientCertificate>

                    <serviceCertificate findValue="MyServer" storeLocation="CurrentUser"

                       x509FindType="FindBySubjectName" />

                  </serviceCredentials>

                </behavior>

            </serviceBehaviors>

        </behaviors>

      <bindings>

        <netTcpBinding>

          <binding name="NewBinding0">

            <security mode="Transport">

              <transport clientCredentialType="Certificate" />

            </security>

          </binding>

        </netTcpBinding>

      </bindings>

        <services>

            <service behaviorConfiguration="Server.MyServiceBehavior" name="Server.MyService">

                <endpoint address="net.tcp://localhost:8081" binding="netTcpBinding" contract="Server.IMyService" bindingConfiguration="NewBinding0"/>              

            </service>

        </services>

    </system.serviceModel>

</configuration>

解释一下:

<authentication certificateValidationMode="Custom" customCertificateValidatorType="Server.CustomX509CertificateValidator,Server"/></clientCertificate>

这一行的意思就是通知WCF服务端,验证客户端证书的模式为自定义,验证时调用Server.CustomX509CertificateValidator这个类来完成验证

<serviceCertificate findValue="MyServer" storeLocation="CurrentUser" x509FindType="FindBySubjectName" />

这一行的意思是WCF服务端验证证书时,到CurrentUser这个位置查询CN=MyServer的证书

最后在Program.cs里启用WCF,内容如下:

using System;  

using System.ServiceModel;

namespace Server

{

    class Program

     {

        static void Main(string[] args)

         {

             ServiceHost host = new ServiceHost(typeof(MyService));

             host.Open();

             Console.ReadKey();

         }

     }

}

build一下,如果编译无错的话,服务端完工,可以运行一下,将弹出一个DOS命令窗口(不过什么输出也没有),只要不报错,就表明Ok了,先不要急着关,尝试浏览一下:

http://localhost:8080/(这个地址哪里来的?回头看下App.config,里面有一行<serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:8080/" />,呵呵,明白了吧) 正常的话,应该类似下图所示:

x.509证书在WCF中的应用 - qiuguangchun - sandea的个人主页

3.客户端调用

下面生成服务端的代理和配置文件,客户端开发将用到这二个文件,同样先进入vs2008的命令行状态,输入:

svcutil.exe http://localhost:8080/ /d:c:\123\

注意:输入这一行命令的时候,请确保服务端程序正在运行。这一句的意思就是在c:\123\目录下输出WCF的代理文件和配置文件

打开vs.net2008,再新建一个控制台应用程序,可以命名为Client

把c:\123\下生成的二个文件MyService.cs,output.config添加到Client项目中,同时将output.config改名为App.Config

Progam.cs代码内容如下:

using System;

namespace Client

{

    class Program

     {

        static void Main(string[] args)

         {

            using (MyServiceClient client = new MyServiceClient())

             {

                 Console.WriteLine("客户端输出:");

                 Console.WriteLine(client.Test());

             }

             Console.ReadKey();

         }

     }

}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值