WCF身份验证之X509证书

X.509 数字证书是在 Internet 环境下,最方便的认证方式

1. 创建数字证书  

    X509证书可以通过 证书颁发机构(如 VeriSign Inc)购买或通过MakeCert.exe 工具创建开发期间使用的临时证书
   .制作一个证书。制作证书:makecert -sr localmachine -ss My -n CN=ejiyuan -sky exchange -pe -r。
       参考:http://msdn.microsoft.com/zh-cn/library/aa702761.aspx
   .导出证书文件,带密钥的pfx文件。使用mmc
   .导入证书到信任的人。
   .导入证书到信任的机构,这个证书就被信任了。

2. 创建服务代码

 [ServiceContract]
    
public interface ICalculator
    {
        [OperationContract]
        
double add(double x, double y);
    }

    
public class CalculatorService : ICalculator
    {

        
public double add(double x, double y)
        {
            
return x + y;
        }
    }
    
class Program
    {
        
static void Main(string[] args)
        {
            ServiceHost _serviceHost 
= new ServiceHost(typeof(CalculatorService));
            _serviceHost.Opened 
+= (s, q) =>
            { 
                Console.WriteLine(
"服务已启动");
                Console.Read(); 
            };
            _serviceHost.Open();
        }
    }

 

 

3. 设置安全验证模式

 

   <bindings>
      
<netTcpBinding>
        
<binding name="nonSessionBinding">
          
<!--当前绑定的安全认证模式-->
          
<security mode="Message" >
            
<!--定义消息级安全性要求的类型,为证书-->
            
<message clientCredentialType="Certificate" />
          
</security>
        
</binding>
      
</netTcpBinding>
    
</bindings>

 

4. 设置服务凭据值

    <behaviors>
      <
serviceBehaviors >
        <
behavior name="CalculatorServiceBehavior" >
          <
serviceCredentials>
            <!--
指定一个 X.509 证书,以供服务用来向使用 Message 安全模式的客户端证明自己的身份-->
            <
serviceCertificate findValue="CN=ejiyuan" x509FindType="FindBySubjectDistinguishedName" storeLocation="LocalMachine" storeName="My"/>
            <
clientCertificate>
              <!--
自定义对客户端进行身份验证的方式-->
              <
authentication certificateValidationMode="Custom" customCertificateValidatorType="Wcf.Extensions.Security.MyX509Validator,Wcf.Extensions.Security" />
            </
clientCertificate>            
          
</serviceCredentials>          
        
</behavior>
      </
serviceBehaviors>
    </
behaviors>

 

 

5. 自定义证书验证
   这里通过证书的指纹码进行认证。每个客户端的数字证书名称和序号的组合都是唯一的指纹码。必须通过继承自'System.IdentityModel.Selectors.X509CertificateValidator',然后我们重写里面的'Validate'方法来实现自己的X509认证逻辑
   可以通过证书相信信息得到 指纹码 如下:
   
  

    public class MyX509Validator : System.IdentityModel.Selectors.X509CertificateValidator
    {
 
        
public override void Validate(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate)
        {
            
if (certificate == null)
            {
                
throw new ArgumentNullException("X509认证证书为空!");
            }
            
if (certificate.Thumbprint != "82fb736f2464c481859f852ecb10f6f9726c265f".ToUpper())
            {
                
throw new System.IdentityModel.Tokens.SecurityTokenException("Certificate Validation Error!");
            }
        }
    }

 

6. 客户端代码

   

class Program
    {
        
static void Main(string[] args)
        {
            CalculatorClient client 
= new CalculatorClient();
            
//查询客户端已安装的证书
            client.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectDistinguishedName, "CN=ejiyuan"); 
            var q 
= client.add(12);
            Console.WriteLine(client.add(
1,2));
            Console.Read();
        }
    }

 

7. 客户端配置信息(自动生成的)    

<system.serviceModel>
        
<bindings>
            
<netTcpBinding>
                
<binding name="NetTcpBinding_ICalculator" >
                    
<security mode="Message">
                        
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
                        
<message clientCredentialType="Certificate" />
                    
</security>
                
</binding>
            
</netTcpBinding>
        
</bindings>
        
<client>
            
<endpoint address="net.tcp://192.168.101.13:8000/calculatorservice"
                binding
="netTcpBinding" bindingConfiguration="NetTcpBinding_ICalculator"
                contract
="ServiceReference1.ICalculator" name="NetTcpBinding_ICalculator">
                
<identity>
                    
<certificate encodedValue="AwAAAAEAAAAUAAAAgvtzbyRkxIGFn4UuyxD2+XJsJl8gAAAAAQAAAPQBAAAwggHwMIIBWaADAgECAhB/oj2gX287pUAmeLEVtWucMA0GCSqGSIb3DQEBBAUAMBIxEDAOBgNVBAMTB2VqaXl1YW4wHhcNMTAwNTI4MDkyNjQzWhcNMzkxMjMxMjM1OTU5WjASMRAwDgYDVQQDEwdlaml5dWFuMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCfOgnw6Vs7gS52Gsud0WsuFOoDeF4+4DL1HFIpQupdExtIkWwY2v2/t/pWHRRvPE/aPf3M6axUYaT4pQqPXBHQR1lb0Hi6XLUGkzsEk7tjiEMEkpt+/8rQIdtXlmmry7yDixoX8PKEd5cGAISjEdbVKJqjQnC55rQXeDYlIXoqlwIDAQABo0cwRTBDBgNVHQEEPDA6gBCTu+dYQbdaauBGEk3SjJ5FoRQwEjEQMA4GA1UEAxMHZWppeXVhboIQf6I9oF9vO6VAJnixFbVrnDANBgkqhkiG9w0BAQQFAAOBgQA1jOywoJ5Xh6B6W3Vw7xPa9A6AH0WtedXPd4YbCU465UdKeP5G2HtKLpS20MnkU6lIh22lxMnb3WGZh70l5Sg1Hl0j/SklLKtOXzeQnVLaPundd9RS1TD/hHwVyu+89cr0866etfGwI9IDpwjhj5ixT3VUHI3eGrXRj+IGx8/W8Q==" />
                
</identity>
            
</endpoint>
        
</client>
    
</system.serviceModel>

 

 

posted @ 2010-05-31 16:54  ejiyuan  阅读(7110)  评论(7编辑  收藏  举报