WCF、HTTPS 与 HTTP [英] WCF, HTTPS vs HTTP

查看:27
本文介绍了WCF、HTTPS 与 HTTP的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有两个样本

对于HTTP:

使用系统;使用 System.Net;使用 System.Net.Security;使用 System.Security.Cryptography.X509Certificates;使用 System.ServiceModel;使用 System.ServiceModel.Description;使用 System.ServiceModel.Security;命名空间 ConsoleApplication1{内部类程序{私有静态无效主(字符串 [] args){string addressHttps = String.Format("http://{0}:51222", Dns.GetHostEntry("").HostName);var wsHttpBinding = new BasicHttpBinding();var serviceHost = new ServiceHost(typeof (HelloWorldService), new Uri(addressHttps));类型端点 = typeof (IHelloWorldService);serviceHost.AddServiceEndpoint(endpoint, wsHttpBinding, "hello");Uri uri = new Uri(serviceHost.Description.Endpoints[0].ListenUri.AbsoluteUri + "/mex");var smb = 新的 ServiceMetadataBehavior();smb.HttpGetEnabled = true;smb.HttpGetUrl = uri;serviceHost.Description.Behaviors.Add(smb);Console.Out.WriteLine("墨西哥地址" + smb.HttpGetUrl);尝试{serviceHost.Open();字符串地址 = serviceHost.Description.Endpoints[0].ListenUri.AbsoluteUri;Console.WriteLine("Listening @ {0}", address);Console.WriteLine("按回车关闭服务");Console.ReadLine();serviceHost.Close();}捕获(通信异常 ce){Console.WriteLine("发生通信错误:{0}", ce.Message);Console.WriteLine();}捕获(例外除外){Console.WriteLine("发生不可预见的错误:{0}", exc.Message);Console.ReadLine();}}}[服务合约]公共接口 IHelloWorldService{【经营合同】字符串说你好(字符串名称);}公共类 HelloWorldService : IHelloWorldService{#region IHelloWorldService 成员公共字符串 SayHello(字符串名称){return string.Format("Hello, {0}", name);}#endregion}}

对于HTTPS

使用系统;使用 System.Net;使用 System.Net.Security;使用 System.Security.Cryptography.X509Certificates;使用 System.ServiceModel;使用 System.ServiceModel.Description;使用 System.ServiceModel.Security;命名空间 ConsoleApplication1{内部类程序{私有静态无效主(字符串 [] args){string addressHttps = String.Format("https://{0}:51222", Dns.GetHostEntry("").HostName);var wsHttpBinding = new BasicHttpBinding();wsHttpBinding.Security.Mode = BasicHttpSecurityMode.Transport;var serviceHost = new ServiceHost(typeof (HelloWorldService), new Uri(addressHttps));类型端点 = typeof (IHelloWorldService);serviceHost.AddServiceEndpoint(endpoint, wsHttpBinding, "hello");serviceHost.Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine,商店名称.我的,X509FindType.FindBySubjectName, "nameofsertificate");serviceHost.Credentials.ClientCertificate.Authentication.RevocationMode = X509RevocationMode.NoCheck;Uri uri = new Uri(serviceHost.Description.Endpoints[0].ListenUri.AbsoluteUri + "/mex");var smb = 新的 ServiceMetadataBehavior();smb.HttpsGetEnabled = true;smb.HttpsGetUrl = uri;serviceHost.Description.Behaviors.Add(smb);Console.Out.WriteLine("墨西哥地址" + smb.HttpsGetUrl);尝试{serviceHost.Open();字符串地址 = serviceHost.Description.Endpoints[0].ListenUri.AbsoluteUri;Console.WriteLine("Listening @ {0}", address);Console.WriteLine("按回车关闭服务");Console.ReadLine();serviceHost.Close();}捕获(通信异常 ce){Console.WriteLine("发生通信错误:{0}", ce.Message);Console.WriteLine();}捕获(例外除外){Console.WriteLine("发生不可预见的错误:{0}", exc.Message);Console.ReadLine();}}public static bool ValidateCertificate(对象发送者,X509Certificate 证书,X509Chain 链,SslPolicyErrors sslPolicyErrors){如果(sslPolicyErrors == SslPolicyErrors.RemoteCertificateChainErrors){foreach (X509ChainStatus chainStatus in chain.ChainStatus){如果(chainStatus.Status == X509ChainStatusFlags.Revoked){返回真;}}}返回假;}}[服务合约]公共接口 IHelloWorldService{【经营合同】字符串说你好(字符串名称);}公共类 HelloWorldService : IHelloWorldService{#region IHelloWorldService 成员公共字符串 SayHello(字符串名称){return string.Format("Hello, {0}", name);}#endregion}}

这些示例开始时没有错误,但如果我尝试创建客户端,我会遇到两种不同的情况:

HTTP - 使用地址成功创建客户端

http://localhost:51222/hello/mex

HTTPS 失败.HTTPS 的地址是:

https://localhost:51222/hello/mex

HTTPS 的错误消息是:

<块引用>

下载时出错https://localhost:51222/hello/mex.底层连接已关闭:发生意外错误发送.身份验证失败,因为远程方已关闭传输流.元数据包含一个无法解析的参考:https://localhost:51222/hello/mex.制作时发生错误HTTP 请求到https://localhost:51222/hello/mex.这可能是由于未配置服务器证书正确使用 HTTPS 中的 HTTP.SYS案件.这也可能是由安全绑定不匹配在客户端和服务器之间.这基础连接已关闭:An发送时发生意外错误.身份验证失败,因为远程方已关闭传输溪流.如果服务定义在当前的解决方案,尝试构建解决方案并添加服务再次参考.

我哪里做错了?

解决方案

我找到了如何决定这个问题的解决方案.所以,服务器的正确代码是:

使用系统;使用 System.Net;使用 System.Security.Cryptography.X509Certificates;使用 System.ServiceModel;使用 System.ServiceModel.Description;命名空间 ConsoleApplication1{内部类程序{私有静态无效主(字符串 [] args){string addressHttps = String.Format("https://{0}:9010", Dns.GetHostEntry("").HostName);var wsHttpBinding = new BasicHttpBinding();wsHttpBinding.Security.Mode = BasicHttpSecurityMode.Transport;wsHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;var serviceHost = new ServiceHost(typeof (HelloWorldService), new Uri(addressHttps));类型端点 = typeof (IHelloWorldService);serviceHost.AddServiceEndpoint(endpoint, wsHttpBinding, "hello");serviceHost.Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine,商店名称.我的,X509FindType.FindBySubjectName, "sergiiz2");var smb = 新的 ServiceMetadataBehavior();smb.HttpsGetEnabled = true;smb.HttpsGetUrl = new Uri(serviceHost.Description.Endpoints[0].ListenUri.AbsoluteUri + "/mex");serviceHost.Description.Behaviors.Add(smb);Console.Out.WriteLine(smb.HttpsGetUrl);尝试{serviceHost.Open();字符串地址 = serviceHost.Description.Endpoints[0].ListenUri.AbsoluteUri;Console.WriteLine("Listening @ {0}", address);Console.WriteLine("按回车关闭服务");Console.ReadLine();serviceHost.Close();}捕获(通信异常 ce){Console.WriteLine("发生通信错误:{0}", ce.Message);Console.WriteLine();}捕获(例外除外){Console.WriteLine("发生不可预见的错误:{0}", exc.Message);Console.ReadLine();}}}[服务合约]公共接口 IHelloWorldService{【经营合同】字符串说你好(字符串名称);}公共类 HelloWorldService : IHelloWorldService{#region IHelloWorldService 成员公共字符串 SayHello(字符串名称){return string.Format("Hello, {0}", name);}#endregion}}

还有几个与证书相关的案例:- 生成证书:

makecert -r -pe -n "CN=%hostname%" -b 01/01/2000 -e 01/01/2050 -eku 1.3.6.1.5.5.7.3.1 -ss my -srlocalMachine -sky exchange -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12

  • 添加监听地址

    httpcfg 设置 urlacl -u https://*:9010/-a D:(A;;GX;;;S-1-5-21-1144070942-1563683482-3278297161-1114)

    莉>
  • 告诉 http.sys 了解 9010 端口上的 ssl 证书

    httpcfg 设置 ssl/i 0.0.0.0:9010/h 8c6e12be537186​​0adfb84cd2ed2351a900731bb8/g "{a2c24c79-b0ef-4783-8ed8-d9138736"

    而且一切正常.

There are two samples

For HTTP:

using System;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Security;

namespace ConsoleApplication1
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            string addressHttps = String.Format("http://{0}:51222", Dns.GetHostEntry("").HostName);
            var wsHttpBinding = new BasicHttpBinding();
            var serviceHost = new ServiceHost(typeof (HelloWorldService), new Uri(addressHttps));
            Type endpoint = typeof (IHelloWorldService);
            serviceHost.AddServiceEndpoint(endpoint, wsHttpBinding, "hello");
            Uri uri = new Uri(serviceHost.Description.Endpoints[0].ListenUri.AbsoluteUri + "/mex");
            var smb = new ServiceMetadataBehavior();
            smb.HttpGetEnabled = true;
            smb.HttpGetUrl = uri;
            serviceHost.Description.Behaviors.Add(smb);
            Console.Out.WriteLine("Mex address  " + smb.HttpGetUrl);
            try
            {
                serviceHost.Open();
                string address = serviceHost.Description.Endpoints[0].ListenUri.AbsoluteUri;
                Console.WriteLine("Listening @ {0}", address);
                Console.WriteLine("Press enter to close the service");
                Console.ReadLine();
                serviceHost.Close();
            }
            catch (CommunicationException ce)
            {
                Console.WriteLine("A commmunication error occurred: {0}", ce.Message);
                Console.WriteLine();
            }
            catch (Exception exc)
            {
                Console.WriteLine("An unforseen error occurred: {0}", exc.Message);
                Console.ReadLine();
            }
        }
    }

    [ServiceContract]
    public interface IHelloWorldService
    {
        [OperationContract]
        string SayHello(string name);
    }

    public class HelloWorldService : IHelloWorldService
    {
        #region IHelloWorldService Members

        public string SayHello(string name)
        {
            return string.Format("Hello, {0}", name);
        }

        #endregion
    }
}

For HTTPS

using System;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Security;

namespace ConsoleApplication1
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            string addressHttps = String.Format("https://{0}:51222", Dns.GetHostEntry("").HostName);
            var wsHttpBinding = new BasicHttpBinding();
            wsHttpBinding.Security.Mode = BasicHttpSecurityMode.Transport;

            var serviceHost = new ServiceHost(typeof (HelloWorldService), new Uri(addressHttps));

            Type endpoint = typeof (IHelloWorldService);

            serviceHost.AddServiceEndpoint(endpoint, wsHttpBinding, "hello");

            serviceHost.Credentials.ServiceCertificate.SetCertificate(
                StoreLocation.LocalMachine,
                StoreName.My,
                X509FindType.FindBySubjectName, "nameofsertificate");

            serviceHost.Credentials.ClientCertificate.Authentication.RevocationMode = X509RevocationMode.NoCheck;

            Uri uri = new Uri(serviceHost.Description.Endpoints[0].ListenUri.AbsoluteUri + "/mex");

            var smb = new ServiceMetadataBehavior();
            smb.HttpsGetEnabled = true;
            smb.HttpsGetUrl = uri;
            serviceHost.Description.Behaviors.Add(smb);

            Console.Out.WriteLine("Mex address  " + smb.HttpsGetUrl);
            try
            {
                serviceHost.Open();

                string address = serviceHost.Description.Endpoints[0].ListenUri.AbsoluteUri;
                Console.WriteLine("Listening @ {0}", address);
                Console.WriteLine("Press enter to close the service");
                Console.ReadLine();
                serviceHost.Close();
            }
            catch (CommunicationException ce)
            {
                Console.WriteLine("A commmunication error occurred: {0}", ce.Message);
                Console.WriteLine();
            }
            catch (Exception exc)
            {
                Console.WriteLine("An unforseen error occurred: {0}", exc.Message);
                Console.ReadLine();
            }
        }
        public static bool ValidateCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateChainErrors)
            {
                foreach (X509ChainStatus chainStatus in chain.ChainStatus)
                {
                    if (chainStatus.Status == X509ChainStatusFlags.Revoked)
                    {
                        return true;
                    }
                }
            }

            return false;
        }
    }

    [ServiceContract]
    public interface IHelloWorldService
    {
        [OperationContract]
        string SayHello(string name);
    }

    public class HelloWorldService : IHelloWorldService
    {
        #region IHelloWorldService Members

        public string SayHello(string name)
        {
            return string.Format("Hello, {0}", name);
        }

        #endregion
    }
}

These samples are starting without errors, but if I try to create clients I have two different situations:

HTTP - the client was created successful using address

http://localhost:51222/hello/mex

And HTTPS failed. The address for HTTPS is:

https://localhost:51222/hello/mex

The error message for HTTPS is:

There was an error downloading https://localhost:51222/hello/mex. The underlying connection was closed: An unexpected error occurred on a send. Authentication failed because the remote party has closed the transport stream. Metadata contains a reference that cannot be resolved: https://localhost:51222/hello/mex. An error occurred while making the HTTP request to https://localhost:51222/hello/mex. This could be due to the fact that the server certificate is not configured properly with HTTP.SYS in the HTTPS case. This could also be caused by a mismatch of the security binding between the client and the server. The underlying connection was closed: An unexpected error occurred on a send. Authentication failed because the remote party has closed the transport stream. If the service is defined in the current solution, try building the solution and adding the service reference again.

Where did I make a mistake?

解决方案

I found solution how to decided this problem. So, the correct code of server is:

using System;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace ConsoleApplication1
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            string addressHttps = String.Format("https://{0}:9010", Dns.GetHostEntry("").HostName);
            var wsHttpBinding = new BasicHttpBinding();
            wsHttpBinding.Security.Mode = BasicHttpSecurityMode.Transport;
            wsHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
            var serviceHost = new ServiceHost(typeof (HelloWorldService), new Uri(addressHttps));
            Type endpoint = typeof (IHelloWorldService);
            serviceHost.AddServiceEndpoint(endpoint, wsHttpBinding, "hello");
            serviceHost.Credentials.ServiceCertificate.SetCertificate(
                StoreLocation.LocalMachine,
                StoreName.My,
                X509FindType.FindBySubjectName, "sergiiz2");
            var smb = new ServiceMetadataBehavior();
            smb.HttpsGetEnabled = true;
            smb.HttpsGetUrl = new Uri(serviceHost.Description.Endpoints[0].ListenUri.AbsoluteUri + "/mex");
            serviceHost.Description.Behaviors.Add(smb);
            Console.Out.WriteLine(smb.HttpsGetUrl);
            try
            {
                serviceHost.Open();

                string address = serviceHost.Description.Endpoints[0].ListenUri.AbsoluteUri;
                Console.WriteLine("Listening @ {0}", address);
                Console.WriteLine("Press enter to close the service");
                Console.ReadLine();
                serviceHost.Close();
            }
            catch (CommunicationException ce)
            {
                Console.WriteLine("A commmunication error occurred: {0}", ce.Message);
                Console.WriteLine();
            }
            catch (Exception exc)
            {
                Console.WriteLine("An unforseen error occurred: {0}", exc.Message);
                Console.ReadLine();
            }
        }
    }

    [ServiceContract]
    public interface IHelloWorldService
    {
        [OperationContract]
        string SayHello(string name);
    }

    public class HelloWorldService : IHelloWorldService
    {
        #region IHelloWorldService Members

        public string SayHello(string name)
        {
            return string.Format("Hello, {0}", name);
        }

        #endregion
    }
}

And a few cases related to certificate: - generating certificate:

makecert -r -pe -n "CN=%hostname%" -b 01/01/2000 -e 01/01/2050 -eku 1.3.6.1.5.5.7.3.1 -ss my -sr localMachine -sky exchange -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12

  • adding url to listening

    httpcfg set urlacl -u https://*:9010/ -a D:(A;;GX;;;S-1-5-21-1144070942-1563683482-3278297161-1114)

  • say to the http.sys to know about ssl certificate on the port 9010

    httpcfg set ssl /i 0.0.0.0:9010 /h 8c6e12be5371860adfb84cd2ed2351a900731bb8 /g "{a2c24c79-b0ef-4783-8ed8-d93836fec137}"

    And all works without problems.

这篇关于WCF、HTTPS 与 HTTP的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆