【问题标题】:Wcf with certificate as ClientCredentials证书作为 ClientCredentials 的 Wcf
【发布时间】:2014-12-13 04:28:42
【问题描述】:

在我的 WCF 自托管 WebService 中使用相互证书来验证客户端,我设置了 CertificateValidationMode = PeerTrust 但它似乎被忽略了,因为我仍然可以使用一些客户端执行方法,我已经删除了 @987654323 的相应证书@服务器存储。

这是主机示例:

  static void Main()
    {
        var httpsUri = new Uri("https://192.168.0.57:xxx/HelloServer");
        var binding = new WSHttpBinding
        {
            Security =
            {
                Mode = SecurityMode.Transport,
                Transport = {ClientCredentialType = HttpClientCredentialType.Certificate}
        };         

        var host = new ServiceHost(typeof(HelloWorld), httpsUri);

        //This line is not working
        host.Credentials.ClientCertificate.Authentication.CertificateValidationMode =X509CertificateValidationMode.PeerTrust;

        host.AddServiceEndpoint(typeof(IHelloWorld), binding, string.Empty, httpsUri);

        host.Credentials.ServiceCertificate.SetCertificate(
            StoreLocation.LocalMachine,
            StoreName.My,
            X509FindType.FindBySubjectName,
            "server.com");

        // Open the service.
        host.Open();
        Console.WriteLine("Listening on {0}...", httpsUri);
        Console.ReadLine();

        // Close the service.
        host.Close();
    }

客户端应用:

 static void Main(string[] args)
    {
        try
        {
            var c = new HelloWorld.HelloWorldClient();
            ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, error) => true;
            c.ClientCredentials.ClientCertificate.SetCertificate(
              StoreLocation.LocalMachine,
              StoreName.My,
              X509FindType.FindBySubjectName,
              "client.com");

            Console.WriteLine(c.GetIp());
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        Console.ReadKey();           
    }

我使用 RootCA 证书生成 server.comclient.com。此 RootCA 证书安装在客户端和服务器的受信任根存储中。 问题是,如果我的 client.com 证书不在服务器的 TrustedPeople 存储中,我不应该执行 GetIp() 方法,对吗?但是我执行它没有任何问题。

问题是,在这种情况下,如何验证客户端证书将其公钥放在服务器的 TrustedPeople 上?

ps:在this MSDN 使用客户端证书的传输安全文章中,引用了The server’s certificate must be trusted by the client and the client’s certificate must be trusted by the server. 但是即使客户端证书不在服务器 TrustedPeople 存储中,我也可以从客户端执行 webmethods。

【问题讨论】:

    标签: c# wcf


    【解决方案1】:

    我的建议是使用custom validation。通过这种方式,您可以设置一些断点并观察验证的发生情况,并根据整个验证过程中可用的数据查看您可以提出哪些其他验证选项。

    首先确保您的绑定需要 消息 客户端凭据的证书。如果您只使用传输证书,我的测试中的客户端没有验证。仅此一项就可以解决您的问题。

    binding.Security.Mode = SecurityMode.TransportWithMessageCredential;
    binding.Security.Message.ClientCredentialType =
            MessageCredentialType.Certificate;
    

    要设置自定义验证器,请遵循其余部分。

    替换:

    host.Credentials.ClientCertificate.Authentication.CertificateValidationMode 
            =X509CertificateValidationMode.PeerTrust;
    

    与:

    host.Credentials.ClientCertificate.Authentication.CertificateValidationMode 
            =X509CertificateValidationMode.Custom;
    
    host.Credentials.ClientCertificate.Authentication.CustomCertificateValidator =
            new IssuerNameCertValidator("CN=client.com");
    

    然后添加这个以创建自定义验证器并根据需要进行调整(这个基于 Issuer 进行验证):

    public class IssuerNameCertValidator : X509CertificateValidator
    {
        string allowedIssuerName;
    
        public IssuerNameCertValidator(string allowedIssuerName)
        {
            if (allowedIssuerName == null)
            {
                throw new ArgumentNullException("allowedIssuerName");
            }
    
            this.allowedIssuerName = allowedIssuerName;
        }
    
        public override void Validate(X509Certificate2 certificate)
        {
            // Check that there is a certificate.
            if (certificate == null)
            {
                throw new ArgumentNullException("certificate");
            }
    
            // Check that the certificate issuer matches the configured issuer.
            if (allowedIssuerName != certificate.IssuerName.Name)
            {
                throw new SecurityTokenValidationException
                  ("Certificate was not issued by a trusted issuer");
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-06-30
      • 1970-01-01
      • 1970-01-01
      • 2013-09-23
      • 2015-09-19
      • 2011-04-13
      • 2012-03-16
      相关资源
      最近更新 更多