具有证书的编程WCF消息安全性

时间:2011-05-18 02:34:33

标签: wcf x509certificate wshttpbinding

我使用WSHttpBindings编写了一个自托管的WCF服务,我正在尝试使用我自己生成的证书来实现消息级安全性。不幸的是,我得到一个隐藏的异常(通过服务跟踪查看器),说明“提供给包的凭据无法识别。”

一对夫妇注意到:

  1. 这必须在代码中完成,而不是 在配置
  2. (服务器/客户端)证书是证书 在本地机器商店 我可以使用私钥 用户在调试时。
  3. 我用谷歌搜索了这个地狱 找到了很好的设置资源 基于WCF消息的安全性here
  4. 我不确定我错过了什么。除了创建端点身份之外,大多数这些东西似乎都是直截了当的。无论我是使用DnsEndpointIdentities,基于证书的,还是根本没有身份,它都会失败并显示相同的消息。

    有人能指出我正确的方向吗?

    服务器端:

    var binding = new WSHttpBinding
        {
          Security =
          {
            Mode = SecurityMode.Message,
            Message = 
            {
              ClientCredentialType = MessageCredentialType.Certificate,
              AlgorithmSuite = SecurityAlgorithmSuite.Basic256Sha256Rsa15
            }
          }
        };
    
    _host = new ServiceHost(this)
    {
      Credentials =
      {
        ServiceCertificate =
        {
          Certificate = ServiceCert
        },
        ClientCertificate =
        {
          Certificate = ClientCert,
          Authentication =
          {
            TrustedStoreLocation = StoreLocation.LocalMachine,
            RevocationMode = X509RevocationMode.NoCheck,
            CertificateValidationMode = X509CertificateValidationMode.PeerOrChainTrust
           }
        }
      }
    };
    var address = new Uri(string.Format(@"http://serviceaddress"));
    var ep = _host.AddServiceEndpoint(typeof (IService), binding, address);
    ep.Address = new EndpointAddress(address, EndpointIdentity.CreateX509CertificateIdentity(ServiceCert));
    _host.Open();
    

    客户方:

    var binding = new WSHttpBinding
        {
          Security =
          {
            Mode = SecurityMode.Message,
            Message =
            { 
              ClientCredentialType = MessageCredentialType.Certificate,
              AlgorithmSuite = SecurityAlgorithmSuite.Basic256Sha256Rsa15
            }
          }
        };
    var address = new Uri(@"http://serviceaddress");
    var endpoint = new EndpointAddress(address, EndpointIdentity.CreateX509CertificateIdentity(ServerCert));
    var channelFactory = new ChannelFactory<IService>(binding, endpoint)
        {
          Credentials =
          {
            ServiceCertificate =
            {
              DefaultCertificate = ServerCert,
              Authentication =
              {
                RevocationMode = X509RevocationMode.NoCheck,
                TrustedStoreLocation = StoreLocation.LocalMachine,
                CertificateValidationMode = X509CertificateValidationMode.PeerOrChainTrust
              }
            },
            ClientCertificate =
            {
              Certificate = ClientCert
            }
          }
        };
    var channel = channelFactory.CreateChannel();
    

1 个答案:

答案 0 :(得分:11)

this msdn article帮了大忙。我认为问题的根源是将以下消息安全性参数设置为false:

httpBinding.Security.Message.NegotiateServiceCredential = false;
httpBinding.Security.Message.EstablishSecurityContext = false;

所以现在服务器端的整体代码看起来更像是:

var httpBinding = new WSHttpBinding(SecurityMode.Message);
httpBinding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;
httpBinding.Security.Message.NegotiateServiceCredential = false;
httpBinding.Security.Message.EstablishSecurityContext = false;
var httpUri = new Uri("http://serviceaddress");
_host = new ServiceHost(this, httpUri);
_host.Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.TrustedPeople, X509FindType.FindByThumbprint, serverThumbprint);
_host.Credentials.ClientCertificate.Authentication.RevocationMode = X509RevocationMode.NoCheck;
_host.Credentials.ClientCertificate.Authentication.TrustedStoreLocation = StoreLocation.LocalMachine;
_host.AddServiceEndpoint(typeof(IMetaService), httpBinding, httpUri);
_host.Open();

和客户方:

var httpBinding = new WSHttpBinding(SecurityMode.Message);
httpBinding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;
httpBinding.Security.Message.NegotiateServiceCredential = false;
httpBinding.Security.Message.EstablishSecurityContext = false;
var httpUri = new Uri("http://serviceaddress");
var httpEndpoint = new EndpointAddress(httpUri, EndpointIdentity.CreateDnsIdentity("name of server cert"));
var newFactory = new ChannelFactory<IMetaService>(httpBinding, httpEndpoint);
newFactory.Credentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.TrustedPeople, X509FindType.FindByThumbprint, "client certificate thumbprint");
newFactory.Credentials.ServiceCertificate.SetDefaultCertificate(StoreLocation.LocalMachine, StoreName.TrustedPeople, X509FindType.FindByThumbprint, "server certificate thumbprint");
var channel = newFactory.CreateChannel();