我有一个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框架库。
请帮助!!!
谢谢!