WCF - Message Security with Mutual Certificates
WCF 相互证书的消息安全
下面是MSDN提供的方案。演示使用消息安全模式保护的 Windows Communication Foundation (WCF) 服务和客户端。 使用证书对客户端和服务进行身份验证。
.gif)
实例代码下载
 
创建服务及客户端证书
相互证书的信息安全需要服务端和客户端进行相互验证,因此我们需要2个证书:服务端证书和客户端证书。接下来我们通过.NET自带的makecert.exe 先创建两个X.509证书:WCF.SecuritySampleCA(服务端)和WCF.SecuritySampleClientCA(客户端)。
Note:以下生成证书过程均在服务端完成。makecert.exe生成的证书只能作为开发测试使用,在正式部署时请不要使用。
创建服务端证书
 makecert.exe -sr LocalMachine -ss MY -a sha1 -n CN=WCF.SecuritySampleCA -sky exchange -pe
makecert.exe -sr LocalMachine -ss MY -a sha1 -n CN=WCF.SecuritySampleCA -sky exchange -peLocalMachine:证书存储在本机。
WCF.SecuritySampleCA:证书的Subject名称。
授予对证书私钥的权限
创建Setup.bat 文件,内容如下。目的是使存储在 LocalMachine 存储中的服务器证书可以供 ASP.NET 工作进程帐户访问。
 echo
echo echo ************
echo ************ echo setting privileges on server certificates
echo setting privileges on server certificates echo ************
echo ************ for /F "delims=" %%i in ('"FindPrivateKey.exe" My LocalMachine -n CN^=WCF.SecuritySampleCA -a') do set PRIVATE_KEY_FILE=%%i
for /F "delims=" %%i in ('"FindPrivateKey.exe" My LocalMachine -n CN^=WCF.SecuritySampleCA -a') do set PRIVATE_KEY_FILE=%%i set WP_ACCOUNT=NT AUTHORITY\NETWORK SERVICE
set WP_ACCOUNT=NT AUTHORITY\NETWORK SERVICE (ver | findstr /C:"5.1") && set WP_ACCOUNT=%COMPUTERNAME%\ASPNET
(ver | findstr /C:"5.1") && set WP_ACCOUNT=%COMPUTERNAME%\ASPNET echo Y|cacls.exe "%PRIVATE_KEY_FILE%" /E /G "%WP_ACCOUNT%":R
echo Y|cacls.exe "%PRIVATE_KEY_FILE%" /E /G "%WP_ACCOUNT%":R pause
pause注意:
如果您使用的是非美国 英文版本的 Microsoft Windows,则必须编辑 Setup.bat 文件,并用与您所在的区域对应的帐户名称替换“NT AUTHORITY\NETWORK SERVICE”帐户名称。
FindPrivateKey.exe可以在实例代码包中找到。
 makecert.exe -sr LocalMachine -ss TrustedPeople -a sha1 -n CN=WCF.SecuritySampleClientCA -sky exchange -pe
makecert.exe -sr LocalMachine -ss TrustedPeople -a sha1 -n CN=WCF.SecuritySampleClientCA -sky exchange -pe导出服务端证书
服务端证书需要在客户端安装,因此需要导出后一起发布到客户端。
1.在运行窗口键入mmc打开证书管理器
2.选择File中的Add/Remove Snap-in
3.弹出窗口中选择Add...
4.选择Certificates -> Add
5.选择Computer account -> Next
6.选择LocalComputer -> Finish
7.Ok后即可进入管理页面
8.右键点击Personal下的Certificates中WCF.SecuritySampleCA
9.All tasks -> Export...
10.按照提示导出服务端证书WCF.SecuritySampleCA.cer,注意不要导出私钥(No,don't export private key)
导出客户端证书
导出后需要在客户端进行安装。
按照上面同样的方法导出客户端证书WCF.SecuritySampleClientCA.cer
创建WCF Service
在解决方案中创建一个WCF Service项目Service.Message.MutualCertificate,引用WcfSecuritySampleLibrary项目。点击此处查看WcfSecuritySampleLibrary相关内容。
配置文件如下:
 <system.serviceModel>
  <system.serviceModel> <services>
    <services> <service name="WcfSecuritySampleLibrary.Service"
      <service name="WcfSecuritySampleLibrary.Service"  behaviorConfiguration="ServiceBehavior">
               behaviorConfiguration="ServiceBehavior"> <!-- Service Endpoints -->
        <!-- Service Endpoints --> <endpoint address=""
        <endpoint address=""  binding="wsHttpBinding"
                  binding="wsHttpBinding"  contract="WcfSecuritySampleLibrary.IService"
                  contract="WcfSecuritySampleLibrary.IService"  bindingConfiguration="WcfSecuritySampleBinding">
                  bindingConfiguration="WcfSecuritySampleBinding"> <!--
          <!--  Upon deployment, the following identity element should be removed or replaced to reflect the
              Upon deployment, the following identity element should be removed or replaced to reflect the  identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity
              identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity  automatically.
              automatically. -->
          --> </endpoint>
        </endpoint> <endpoint address="mex"
        <endpoint address="mex"  binding="mexHttpBinding"
                  binding="mexHttpBinding"  contract="IMetadataExchange"/>
                  contract="IMetadataExchange"/> </service>
      </service> </services>
    </services> <bindings>
      <bindings> <wsHttpBinding>
          <wsHttpBinding> <binding name="WcfSecuritySampleBinding">
              <binding name="WcfSecuritySampleBinding"> <security mode="Message">
                  <security mode="Message"> <message clientCredentialType="Certificate"
                      <message clientCredentialType="Certificate"  establishSecurityContext="false"
                               establishSecurityContext="false"  negotiateServiceCredential="false"/>
                               negotiateServiceCredential="false"/> </security>
                  </security> </binding>
              </binding> </wsHttpBinding>
          </wsHttpBinding> </bindings>
      </bindings> <behaviors>
    <behaviors> <serviceBehaviors>
      <serviceBehaviors> <behavior name="ServiceBehavior">
        <behavior name="ServiceBehavior"> <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment --> <serviceMetadata httpGetEnabled="true"/>
          <serviceMetadata httpGetEnabled="true"/> <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information --> <serviceDebug includeExceptionDetailInFaults="false"/>
          <serviceDebug includeExceptionDetailInFaults="false"/> <serviceCredentials>
            <serviceCredentials> <serviceCertificate storeLocation="LocalMachine"
                <serviceCertificate storeLocation="LocalMachine"  findValue="WCF.SecuritySampleCA"
                                    findValue="WCF.SecuritySampleCA"  storeName="My"
                                    storeName="My"  x509FindType="FindBySubjectName"/>
                                    x509FindType="FindBySubjectName"/> <clientCertificate>
                <clientCertificate> <!--
                    <!--  Setting the certificateValidationMode to PeerOrChainTrust means that if the certificate
        Setting the certificateValidationMode to PeerOrChainTrust means that if the certificate  is in the user's Trusted People store, then it is trusted without performing a
        is in the user's Trusted People store, then it is trusted without performing a validation of the certificate's issuer chain. This setting is used here for convenience so that the
        validation of the certificate's issuer chain. This setting is used here for convenience so that the  sample can be run without having certificates issued by a certificate authority (CA).
        sample can be run without having certificates issued by a certificate authority (CA). This setting is less secure than the default, ChainTrust. The security implications of this
        This setting is less secure than the default, ChainTrust. The security implications of this  setting should be carefully considered before using PeerOrChainTrust in production code.
        setting should be carefully considered before using PeerOrChainTrust in production code.  -->
        --> <authentication certificateValidationMode="PeerOrChainTrust" />
                    <authentication certificateValidationMode="PeerOrChainTrust" /> </clientCertificate>
                </clientCertificate> </serviceCredentials>
            </serviceCredentials> </behavior>
        </behavior> </serviceBehaviors>
      </serviceBehaviors> </behaviors>
    </behaviors> </system.serviceModel>
  </system.serviceModel>在IIS上部署WCF Service
编译通过后,将WCF Service部署到IIS上。
创建站点WCF.SecuritySampleService,然后为该站点绑定服务证书:
1.右键Properties -> Dictionary Security -> Server Cetificate
2.根据提示选择Assign an existing certificate, 然后选择证书WCF.SecuritySampleCA
3.设置端口
证书绑定后,即可添加一个虚拟目录创建WCF Service。

使用浏览器浏览该Service中的Service.svc,配置成功的话,即可打开如下页面:

在Visual Studio 命令提示窗口键入如下命令,生成代理类Service.cs及客户端配置文件output.config。
 svcutil.exe http://leo.isoftstone.com:6515/Service.Message.MutualCertificate/Service.svc?wsdl
svcutil.exe http://leo.isoftstone.com:6515/Service.Message.MutualCertificate/Service.svc?wsdl创建客户端
解决方案中创建客户端项目Client.Message.MutualCertificate。具体实现参见实例中的2个项目Client.Message.MutualCertificate和BusinessLibrary。
安装证书
消息安全的互相验证需要在客户端安装服务端和客户端2个证书。安装方法很简单,只要双击在服务端导出的2个证书WCF.SecuritySampleCA.cer和WCF.SecuritySampleClientCA.cer,根据提示安装即可。
例如安装服务端证书:(服务端证书需要安装在客户端CurrentUser的Trusted People中)
1.双击证书
2.点击Install Certificate...
3.下一步后选择Place all certificates in the following store,然后点击Browse...

4.弹出窗口中选择Trusted People

5.OK.
客户端证书的安装步骤如上,唯一的区别是最后选择证书存储的路径不是Trusted People而是Personal。
客户端配置
 <system.serviceModel>
<system.serviceModel> <bindings>
        <bindings> <wsHttpBinding>
            <wsHttpBinding> <binding name="WSHttpBinding_IService">
                <binding name="WSHttpBinding_IService"> <security mode="Message">
                    <security mode="Message"> <message clientCredentialType="Certificate"
                        <message clientCredentialType="Certificate"  establishSecurityContext="false"
                                 establishSecurityContext="false"  negotiateServiceCredential="false"/>
                                 negotiateServiceCredential="false"/> </security>
                    </security> </binding>
                </binding> </wsHttpBinding>
            </wsHttpBinding> </bindings>
        </bindings> <client>
        <client> <endpoint address="http://leo.isoftstone.com:6515/Service.Message.MutualCertificate/Service.svc"
            <endpoint address="http://leo.isoftstone.com:6515/Service.Message.MutualCertificate/Service.svc" binding="wsHttpBinding"
                      binding="wsHttpBinding"  bindingConfiguration="WSHttpBinding_IService"
                      bindingConfiguration="WSHttpBinding_IService" contract="IService"
                      contract="IService"  name="WSHttpBinding_IService"
                      name="WSHttpBinding_IService"  behaviorConfiguration="ClientCredentialsBehavior">
                      behaviorConfiguration="ClientCredentialsBehavior"> <identity>
                <identity> <certificate encodedValue="AwAAAAEAAAAUAAAAv1KUaGzvpF2I/2nb55A3qyb4+QUgAAAAAQAAAMABAAAwggG8MIIBaqADAgECAhBL/0cYj41XmU7yomd4SulEMAkGBSsOAwIdBQAwFjEUMBIGA1UEAxMLUm9vdCBBZ2VuY3kwHhcNMDgwNjA2MDc0MjAxWhcNMzkxMjMxMjM1OTU5WjAfMR0wGwYDVQQDExRXQ0YuU2VjdXJpdHlTYW1wbGVDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzbZ8uOt+yvfZHqp0pqmEYiv+S/2t4msC1mP4hkWK8nHT38vhOaHk3QYuaLDaBo1+cPPlhi2wsE+3aQteScsQTYbAiFkHVGhcSsxVCfnT6YdOA39Rpmc66EnZmiM8t1FAKGfD5jAe17lQN63hKk4jM3HbV/QTw3+IvxgkP7eKTSECAwEAAaNLMEkwRwYDVR0BBEAwPoAQEuQJLQYdHU8AjWEh3BZkY6EYMBYxFDASBgNVBAMTC1Jvb3QgQWdlbmN5ghAGN2wAqgBkihHPuNSqXDX0MAkGBSsOAwIdBQADQQBbx4i4WMz7tb7CjFQogCjoR1Z4gdMUY1Nb/4T/RP90aINADATRHYShYDduq8kU89e5BcwhvUBoacclkBUFGCof" />
                    <certificate encodedValue="AwAAAAEAAAAUAAAAv1KUaGzvpF2I/2nb55A3qyb4+QUgAAAAAQAAAMABAAAwggG8MIIBaqADAgECAhBL/0cYj41XmU7yomd4SulEMAkGBSsOAwIdBQAwFjEUMBIGA1UEAxMLUm9vdCBBZ2VuY3kwHhcNMDgwNjA2MDc0MjAxWhcNMzkxMjMxMjM1OTU5WjAfMR0wGwYDVQQDExRXQ0YuU2VjdXJpdHlTYW1wbGVDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzbZ8uOt+yvfZHqp0pqmEYiv+S/2t4msC1mP4hkWK8nHT38vhOaHk3QYuaLDaBo1+cPPlhi2wsE+3aQteScsQTYbAiFkHVGhcSsxVCfnT6YdOA39Rpmc66EnZmiM8t1FAKGfD5jAe17lQN63hKk4jM3HbV/QTw3+IvxgkP7eKTSECAwEAAaNLMEkwRwYDVR0BBEAwPoAQEuQJLQYdHU8AjWEh3BZkY6EYMBYxFDASBgNVBAMTC1Jvb3QgQWdlbmN5ghAGN2wAqgBkihHPuNSqXDX0MAkGBSsOAwIdBQADQQBbx4i4WMz7tb7CjFQogCjoR1Z4gdMUY1Nb/4T/RP90aINADATRHYShYDduq8kU89e5BcwhvUBoacclkBUFGCof" /> </identity>
                </identity> </endpoint>
            </endpoint> </client>
        </client> <behaviors>
        <behaviors> <endpointBehaviors>
            <endpointBehaviors> <behavior name="ClientCredentialsBehavior">
                <behavior name="ClientCredentialsBehavior"> <clientCredentials>
                    <clientCredentials> <clientCertificate findValue="WCF.SecuritySampleClientCA"
                        <clientCertificate findValue="WCF.SecuritySampleClientCA" storeLocation="CurrentUser"
                                           storeLocation="CurrentUser" storeName="My"
                                           storeName="My" x509FindType="FindBySubjectName"/>
                                           x509FindType="FindBySubjectName"/> <serviceCertificate>
                        <serviceCertificate> <defaultCertificate findValue="WCF.SecuritySampleCA"
                            <defaultCertificate findValue="WCF.SecuritySampleCA" storeLocation="CurrentUser"
                                                storeLocation="CurrentUser" storeName="TrustedPeople"
                                                storeName="TrustedPeople" x509FindType="FindBySubjectName"/>
                                                x509FindType="FindBySubjectName"/> </serviceCertificate>
                        </serviceCertificate> </clientCredentials>
                    </clientCredentials>             </behavior>
                </behavior> </endpointBehaviors>
            </endpointBehaviors> </behaviors>
        </behaviors> </system.serviceModel>
    </system.serviceModel>
 
                    
                 
                
            
         
 浙公网安备 33010602011771号
浙公网安备 33010602011771号