Windows 10 Universal WCF生成的客户端设置忽略ssl证书错误

时间:2016-12-14 19:16:13

标签: c# .net wcf windows-10-universal

我有一个Windows 10 UWP应用程序,它使用WCF来调用我们现有的服务。该服务已添加到我的项目中,方法是将其添加为服务引用,然后自动生成大部分代码和WCF客户端。客户端和服务都只在内部运行。该服务在IIS服务器上运行,并具有自签名证书。因此,我们在访问或浏览服务时通常会收到证书错误。这是好的和预期的,坦率地说,我们只是想忽略它,因为我们只是内部。

也就是说,在过去的应用程序中(所有应用程序都是用.Net编写的,但是使用完整的框架)我们只需使用以下代码来设置客户端。

    public PacTracMobileServerClient GetClient()
    {
        try
        {
            AppConfig config = new AppConfig();
            string url = config.GetODSServerAddress;

            CustomBinding binding = new CustomBinding();
            //TODO Make these timeouts configurable as well
            binding.SendTimeout = TimeSpan.FromMinutes(10);
            binding.ReceiveTimeout = TimeSpan.FromMinutes(10);

            TextMessageEncodingBindingElement tme = new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8);
            binding.Elements.Add(tme);

            if (url.StartsWith("https", StringComparison.CurrentCultureIgnoreCase))
            {
                //HTTPS binding
                HttpsTransportBindingElement https = new HttpsTransportBindingElement();
                https.MaxReceivedMessageSize = int.MaxValue;
                https.MaxBufferSize = int.MaxValue;
                https.RequireClientCertificate = false;
                binding.Elements.Add(https);

                //Trust all certificates
                ServicePointManager.ServerCertificateValidationCallback = delegate (object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; };
            }
            else
            {
                //HTTP binding
                HttpTransportBindingElement http = new HttpTransportBindingElement();
                http.MaxReceivedMessageSize = int.MaxValue;
                http.MaxBufferSize = int.MaxValue;
                binding.Elements.Add(http);
            }

            var ODSUri = new System.Uri(url);
            var endPoint = new EndpointAddress(ODSUri);

            var client = new PacTracMobileServerClient(binding, endPoint);

            return client;
        }
        catch (Exception ex)
        {

            return null;
        }
    }

以上的关键是行:

 ServicePointManager.ServerCertificateValidationCallback = delegate (object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; };

我已经确认使用我们其他现有的非Windows 10 UWP应用程序,如果我注释掉该行,我会得到类似的错误。如果我保留它,我可以正常访问该服务,没有错误。

因此,我需要类似于Windows 10 UWP的东西。但是,ServicePointManager命名空间在UWP中不可用。我已经看到了诸如创建http过滤器之类的东西,然后将其传递到httpClient以忽略证书,但由于我使用生成的WCF客户端,因此我没有httpClient。

我一直在研究这个很多但是因为我们是Windows 10 UWP并使用WCF生成的代码,我似乎无法找到这个特定问题的全部内容。

我发现的一件事似乎很有希望和尝试,但没有奏效,那就是:

    public PacTracMobileServerClient GetClient()
    {
        try
        {
            AppConfig config = new AppConfig();
            string url = config.GetODSServerAddress;

            CustomBinding binding = new CustomBinding();
            //TODO Make these timeouts configurable as well
            binding.SendTimeout = TimeSpan.FromMinutes(10);
            binding.ReceiveTimeout = TimeSpan.FromMinutes(10);

            TextMessageEncodingBindingElement tme = new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8);
            binding.Elements.Add(tme);

            if (url.StartsWith("https", StringComparison.CurrentCultureIgnoreCase))
            {
                //HTTPS binding
                HttpsTransportBindingElement https = new HttpsTransportBindingElement();
                https.MaxReceivedMessageSize = int.MaxValue;
                https.MaxBufferSize = int.MaxValue;
                https.RequireClientCertificate = false;
                binding.Elements.Add(https);

                //Trust all certificates
                //ServicePointManager.ServerCertificateValidationCallback = delegate (object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; };
            }
            else
            {
                //HTTP binding
                HttpTransportBindingElement http = new HttpTransportBindingElement();
                http.MaxReceivedMessageSize = int.MaxValue;
                http.MaxBufferSize = int.MaxValue;
                binding.Elements.Add(http);
            }

            var ODSUri = new System.Uri(url);
            var endPoint = new EndpointAddress(ODSUri);

            var client = new PacTracMobileServerClient(binding, endPoint);
            client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;

            return client;
        }
        catch (Exception ex)
        {

            return null;
        }
    }

特别是在我这样做的地方:

                 client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;

注意,上面的方法,GetClient,在这两种情况下都能正常工作,并且会给我一个客户端。但是,当我实际尝试针对该客户端调用WCF方法时,我得到一个例外:

  

net_http_client_execution_error

更新:我试图在这里开箱即用,以找到解决方案。考虑到UWP(.net核心),WCF和SSL客户端证书的组合,我似乎找到了一个无法修复的漏洞。这已经花了我几天,我今天花了一整天研究,并认为我找到了一些东西,但它仍然没有用。这就是我所做的,在生成的服务引用代码中,我找到了创建客户端的类。我看到它继承自System.ServiceModel.ClientBase。所以,我创建了这个类:

public class MyCertificateValidator : X509CertificateValidator
{
    public MyCertificateValidator()
    {

    }

    public override void Validate(X509Certificate2 certificate)
    {

    }
}

我读过如果validate方法返回,则假定证书已经过验证。所以,我把这个方法留空了以便它返回。然后我在创建客户端的地方做了这个

        this.ChannelFactory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.Custom;
        this.ChannelFactory.Credentials.ServiceCertificate.Authentication.CustomCertificateValidator = new MyCertificateValidator();

这似乎应该有效,但事实并非如此。有这个想法吗?

我还研究了在.Net classic中创建一个包装类库,并且类库本身工作正常,因为通过拥有完整的.Net框架,我可以再次这样做:

ServicePointManager.ServerCertificateValidationCallback = delegate(object s,X509Certificate certificate,X509Chain chain,SslPolicyErrors sslPolicyErrors){return true; };

但是,当我构建.dll时,我无法从我的UWP应用程序中引用它。当我尝试添加引用时,它表示不允许在.net核心应用程序中引用.net框架库。

请帮助!!!

谢谢!

0 个答案:

没有答案