【问题标题】:WCF Self Host Via Https FailsWCF 自主机通过 Https 失败
【发布时间】:2026-01-05 07:05:02
【问题描述】:

所以我被困在这里了。我一直能够通过 http 毫无问题地托管 WCF 应用程序。我可以在 IIS 中设置 https WCF 应用程序。但是当我尝试使用自托管的 https wcf 应用程序时,这只不过是一场噩梦。 我在同一台计算机上同时运行客户端和自托管服务。此外,每次我运行该服务时都会打开它而没有错误。据报道状态是开放的。当我尝试与客户端连接(通过通道工厂激活服务)时,它会因 SSL/TLS 错误而崩溃,如下所述。我已经在这工作了大约 2 天,但无法让它工作:(

我已尝试遵循几个指南,例如(但不限于)此处的指南:http://blogs.msdn.com/b/james_osbornes_blog/archive/2010/12/10/selfhosting-a-wcf-service-over-https.aspx 以及此处的指南:http://msdn.microsoft.com/en-us/library/ms733791.aspx。第一个文档我遵循它,最后当作者说“就是这样!现在我们可以调用程序,它会调用服务”时它没有。它给了我一个错误:

“无法为 SSL/TLS 安全通道建立信任关系”。

所以我在开始第二篇文章时尝试了一种稍微不同的方法。我尝试使用已为我的服务器列出的现有认证(存储在个人认证下)。我复制了指纹并将其注册到创建我自己的应用程序 ID 的端口。那没有用,所以我想好让我们尝试通过指定客户端凭据并通过指纹查找它来强制服务和客户端上的客户端证书指纹,如下所示:

factory.Credentials.ClientCertificate.SetCertificate(
    StoreLocation.LocalMachine, 
    StoreName.My,          
    X509FindType.FindByThumbprint, 
    "The actual thumbprint is here in my code");

我仍然得到相同的结果。我错过了什么?这是服务和客户端的代码。

客户:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ServiceModel;
using HttpsSelfHost;

namespace ConsoleApp4
{
    class Program
    {
        static void Main(string[] args)
        {
            string address = "https://localhost:8007/HelloWorldSvc";
            WSHttpBinding binding = new WSHttpBinding();
            binding.Security.Mode = SecurityMode.Transport;
            binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;

            try
            {
                ChannelFactory<IHelloWorldSvc> factory = new ChannelFactory<IHelloWorldSvc>(binding, address);
                factory.Credentials.ClientCertificate.SetCertificate(System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine, System.Security.Cryptography.X509Certificates.StoreName.My,
                    System.Security.Cryptography.X509Certificates.X509FindType.FindByThumbprint, "f80e16f75e805b951e6099979f6dcea56bce3273");
                IHelloWorldSvc client = factory.CreateChannel();
                Console.WriteLine("Invoking service.");
                string str = client.HelloWorld();
                Console.WriteLine("Returned: {0}", str);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            Console.WriteLine("Press enter to quit.");
            Console.ReadLine();
        }
    }
}

服务:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ServiceModel;

namespace HttpsSelfHost
{
    class Program
    {
        static void Main(string[] args)
        {
            string address = "https://localhost:8007/HelloWorldSvc";
            WSHttpBinding binding = new WSHttpBinding();
            binding.Security.Mode = SecurityMode.Transport;
            binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
            using (ServiceHost host = new ServiceHost(typeof(HelloWorldSvc)))
            {
                host.AddServiceEndpoint(typeof(IHelloWorldSvc), binding, address);
                host.Credentials.ClientCertificate.SetCertificate(System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine, System.Security.Cryptography.X509Certificates.StoreName.My,
                    System.Security.Cryptography.X509Certificates.X509FindType.FindByThumbprint, "f80e16f75e805b951e6099979f6dcea56bce3273");
                host.Open();

                Console.WriteLine("Host is: {0}. Press enter to close.", host.State);
                Console.ReadLine();
                host.Close();
            }
        }
    }
}

【问题讨论】:

  • 添加证书验证后是否仍然出现同样的错误?

标签: c# wcf host self


【解决方案1】:

您的客户可能在协商过程中拒绝了证书。我怀疑您在主机正在侦听的端口上绑定的证书是自签名的。

如果您对证书固定没问题,您可以在测试环境和生产环境中的客户端上使用以下内容。

/// <summary>
/// Sets the Certificate Validation Policy for the Client
/// </summary>
public static void SetCertificatePolicy()
{
    ServicePointManager.ServerCertificateValidationCallback 
                                          += ValidateRemoteCertificate;
}

/// <summary>
/// Allows for validation of SSL conversations with the server. 
/// </summary>
private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, 
                                        X509Chain chain, SslPolicyErrors error)
{
    if (cert.GetCertHashString() == "Your Certificate SHA1 HashString")
    {
       return true;
    }
    else
    {
       string text = "Failed to establish secure channel for SSL/TLS." 
                     + Environment.NewLine + Environment.NewLine +
                     "Connection with server has been disallowed.";
       MessageBox.Show(text, @"SSL Validation Failure", 
                    MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
       return false;
    }
}

【讨论】:

  • 当我下班时,我会尝试调查我没有听说过证书固定。我正在使用自签名证书。到目前为止感谢您的建议! :)
  • 你在客户端上试过了吗?
  • 我做到了,它给了我所需的信息。证书是小写的 >
  • 我会指出我确实复制并粘贴了我最初使用的代码。
  • 我认为这是一个权限问题,IIS 不允许服务在任何端口或其他东西上与 locahost 通信。我不明白为什么当相同的代码在控制台应用程序中运行时服务调用会失败,只是在同一台机器上的 IIS 中托管的 Web 服务中不起作用。我一直在研究可能的问题,但到目前为止还没有结果。