不带IIS的HTTPS上的WCF服务,带有来自CERT和KEY字符串或文件的SSL证书

时间:2019-02-17 14:33:34

标签: c# wcf

我以前曾与WCF进行过合作-但由于它仅用于内部使用,根本无法从Internet访问,因此我只是使用net.tcp而不关心安全性。

但是,我现在正在准备一个项目,该项目可以通过Internet向客户提供,因此必须考虑安全性。

我一直在对此事进行一些研究,从我收集到的信息(如果我在这里错了,请更正),HTTPS是我最好的选择,因为HTTP根本没有保护(默认情况下)和网络。 tcp可能会发现某些防火墙有问题。

但是,我不想强​​迫客户如果不想在他们的服务器上安装IIS,因此计划是使用自托管的Windows服务。但是,我似乎找不到任何有关如何设置服务器以在没有IIS的情况下使用HTTPS的信息。

  1. 我发现了有关使用makecerthttpcfg set ssl向商店添加新证书,然后将其设置为端口的信息-可以进行测试,但是我认为这不太可行在客户的服务器中-更不用说这意味着我将使用自己签署的证书-再次可以进行测试,而在生产中则不需要那么多

  2. 我还找到了有关使用类似内容的信息(ServiceCredentials MSDN page

    sh.Credentials.ServiceCertificate.SetCertificate(
        StoreLocation.LocalMachine, StoreName.My,
        X509FindType.FindByThumbprint, 
        "af1f50b20cd413ed9cd00c315bbb6dc1c08da5e6");
    

设置服务器证书存储区中已经存在的证书-几乎可以-仍然需要客户知道如何管理存储区中的证书,虽然不是很完美,但是还可以。但是我无法使它正常工作-启动Servisse时没有任何错误,但是如果我尝试在浏览器中转到服务地址,则会收到关于TLS蜂鸣声过时的错误-Q1:任何想法可能是这里的问题吗?

Q2:是否有可能在某个地方进行配置,客户可以在其中购买购买证书并使用它来确保服务安全时输入的证书和密钥文件的拥有或至少存储位置?

1 个答案:

答案 0 :(得分:0)

Q1:如错误所述,证书中可能存在问题。确保证书有效(自签名证书不能过期)。
Q2:据我所知,我们可以将证书另存为文件(pfx,cert)或将证书安装在证书存储区(certlm.msc,certmgr.msc)中以便进行管理。
是否要在Windows服务项目中通过https托管WCF服务?我做了一个演示,希望对您有用。
Service1.cs

public partial class Service1 : ServiceBase
        {
            public Service1()
            {
                InitializeComponent();
            }
            Uri uri = new Uri("https://localhost:1017");
            ServiceHost sh = null;
            protected override void OnStart(string[] args)
            {
                BasicHttpBinding binding = new BasicHttpBinding();
                binding.Security.Mode = BasicHttpSecurityMode.Transport;
                binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
                try
                {
                    ServiceHost sh = new ServiceHost(typeof(MyService), uri);
                    sh.AddServiceEndpoint(typeof(IService), binding, "");
                    ServiceMetadataBehavior smb;
                    smb = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
                    if (smb == null)
                    {
                        smb = new ServiceMetadataBehavior()
                        {
                            HttpsGetEnabled=true,
                        };
                        sh.Description.Behaviors.Add(smb);
                    }
                    Binding mexbinding = MetadataExchangeBindings.CreateMexHttpsBinding();
                    sh.AddServiceEndpoint(typeof(IMetadataExchange), mexbinding, "mex");
                    sh.Open();
                    WriteLog($"Service is ready at {DateTime.Now.ToString("hh-mm-ss")}");
                }
                catch (Exception e)
                {
                    WriteLog(e.ToString());
                    throw;
                }
            }

            protected override void OnStop()
            {
                if (sh!=null&&sh.State==CommunicationState.Opened)
                {
                    sh.Close();
                    WriteLog($"Service is closed at {DateTime.Now.ToString("hh-mm-ss")}");
                }
            }

            public static void WriteLog(string text)
            {
                using (StreamWriter sw = File.AppendText(@"C:\Mylog.txt"))
                {
                    sw.WriteLine(text);
                    sw.Flush();
                }
            }
        }
        [ServiceContract(Namespace = "mydomain")]
        public interface IService
        {
            [OperationContract]
            string SayHello();
        }
        public class MyService : IService
        {
            public string SayHello()
            {
                Service1.WriteLog(string.Format("Wow, I have been called at {0}", DateTime.Now.ToString("hh-mm-ss")));
                return "Hello stranger";
            }
    }

ProjectInstaller.cs
enter image description here
enter image description here
安装Windows服务(管理员权限CMD)
enter image description here
将证书绑定到应用程序端口。
enter image description here
https://docs.microsoft.com/en-us/windows/desktop/http/add-sslcert
https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-configure-a-port-with-an-ssl-certificate
Certhash参数指定证书的指纹。 appid参数是一个GUID,可用于标识拥有的应用程序(打开project.csproj文件)

<ProjectGuid>{56FDE5B9-3821-49DB-82D3-9DCE376D950A}</ProjectGuid>

启动Windows服务。
enter image description here
测试(服务器IP为10.157.13.70):
enter image description here
客户端调用(默认情况下会有一个验证服务器证书的步骤)

static void Main(string[] args)
    {
        ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
        ServiceReference1.ServiceClient client = new ServiceReference1.ServiceClient();
        try
        {
            var result = client.SayHello();
            Console.WriteLine(result);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }

结果
enter image description here
随时让我知道是否有什么可以帮助您的。