xamarin 异常错误:找不到凭证路径的信任起点

pdtvr36n  于 2022-12-07  发布在  其他
关注(0)|答案(3)|浏览(171)

在Xamarin中。我一直在尝试在我的Web API和我的Xamarin项目之间进行通信。下面是我的控制器的代码:

//  GET api/values
    public List<string> Get()
    {
        List<string> values = new List<string>();
        values.Add("Value 1");
        values.Add("Value 2");
        return values;
    }

这是我的MainPage. xaml. cs中的GET请求

public async void BindToListView()
    {
        HttpClient client = new HttpClient();
        var response = await client.GetStringAsync("https://10.0.2.2:#####/api/Values");
        var posts = JsonConvert.DeserializeObject<List<Posts>>(response);
        lv.ItemsSource = posts;
    }

每当我尝试同时运行我的Android应用程序和Web API应用程序时,我总是会遇到以下异常:

Javax.Net.Ssl.SSLHandshakeException: 
'java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.'

我已经尝试将其粘贴到我的MainActivity. cs中,但仍然不起作用。

ServicePointManager.ServerCertificateValidationCallback += (o, cert, chain, errors) => true;

这个问题已经困扰了我几个月了,它让我抓狂。我错过了什么吗?我在开发Xamarin应用程序方面还是个新手,这个问题我似乎无法解决。
任何关于如何解决这个问题的建议都将非常感谢。感谢您花时间阅读本文。

knpiaxh1

knpiaxh11#

//Use this, it worked for me. 

HttpClient client;

public class datastore {
   var httpClientHandler = new HttpClientHandler();
            
   httpClientHandler.ServerCertificateCustomValidationCallback = 
   (message, cert, chain, errors) => { return true; };

   client = new HttpClient(httpClientHandler);
}

//... use the client to make request. it will bypass 
//the ssl certificates verification.
ukxgm1gy

ukxgm1gy2#

对于Android,你应该做更多的事情。

在Forms中创建接口

public interface IHTTPClientHandlerCreationService
{
  HttpClientHandler GetInsecureHandler();
}

在Android中实现了该接口:

[assembly: Dependency(typeof(HTTPClientHandlerCreationService_Android))]
namespace xxx.Droid
{
  public class HTTPClientHandlerCreationService_Android : CollateralUploader.Services.IHTTPClientHandlerCreationService
  {
    public HttpClientHandler GetInsecureHandler()
    {
      return new IgnoreSSLClientHandler();
    }
  }

  internal class IgnoreSSLClientHandler : AndroidClientHandler
  {
    protected override SSLSocketFactory ConfigureCustomSSLSocketFactory(HttpsURLConnection connection)
    {
      return SSLCertificateSocketFactory.GetInsecure(1000, null);
    }

    protected override IHostnameVerifier GetSSLHostnameVerifier(HttpsURLConnection connection)
    {
      return new IgnoreSSLHostnameVerifier();
    }
  }

  internal class IgnoreSSLHostnameVerifier : Java.Lang.Object, IHostnameVerifier
  {
    public bool Verify(string hostname, ISSLSession session)
    {
      return true;
    }
  }
}

当你调用Get方法时

public async void BindToListView()
{
  HttpClient client;

  switch (Device.RuntimePlatform)
  {
    case Device.Android:
      this.httpClient = new HttpClient(DependencyService.Get<Services.IHTTPClientHandlerCreationService>().GetInsecureHandler());
      break;
    default:
      ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
      this.httpClient = new HttpClient(new HttpClientHandler());
      break;
  }

  var response = await client.GetStringAsync("https://10.0.2.2:#####/api/Values");
  var posts = JsonConvert.DeserializeObject<ObservableCollection<Posts>>(response);
  lv.ItemsSource = posts;
}

另外,我建议您可以使用ObservableCollection而不是List,因为它实现了接口INotifyPropertyChanged,否则UI将永远不会更新。

bjg7j2ky

bjg7j2ky3#

尝试从Android模拟器中运行的.NET MAUI应用调用本地安全Web服务将导致抛出java.security.cert.CertPathValidatorException,并显示一条消息,指示尚未找到证书路径的信任锚。尝试从调用本地安全Web服务。NET MAUI应用程序在iOS模拟器中运行将导致NSURLErrorDomain错误,并显示一条消息,指出服务器的证书无效。发生这些错误的原因是本地HTTPS开发证书是自签名的,而Android或iOS不信任自签名证书。因此,当应用使用本地安全Web服务时,有必要忽略SSL错误。
这可以通过将本地HttpMessageHandler类的配置版本传递给HttpClient构造函数来实现,该构造函数指示HttpClient类信任HTTPS上的本地主机通信。HttpMessageHandler类是一个抽象类,其在Android上的实现由AndroidMessageHandler类提供,而其在iOS上的实现由NSUrlSessionHandler类提供。
以下示例显示了一个类,该类将Android上的AndroidMessageHandler类和iOS上的NSUrlSessionHandler类配置为信任通过HTTPS进行的本地主机通信:C#语言

public class HttpsClientHandlerService
{
    public HttpMessageHandler GetPlatformMessageHandler()
    {
#if ANDROID
        var handler = new CustomAndroidMessageHandler();
        handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
        {
            if (cert != null && cert.Issuer.Equals("CN=localhost"))
                return true;
            return errors == System.Net.Security.SslPolicyErrors.None;
        };
        return handler;
#elif IOS
        var handler = new NSUrlSessionHandler
        {
            TrustOverrideForUrl = IsHttpsLocalhost
        };
        return handler;
#else
     throw new PlatformNotSupportedException("Only Android and iOS supported.");
#endif
    }

#if ANDROID
    internal sealed class CustomAndroidMessageHandler : Xamarin.Android.Net.AndroidMessageHandler
    {
        protected override Javax.Net.Ssl.IHostnameVerifier GetSSLHostnameVerifier(Javax.Net.Ssl.HttpsURLConnection connection)
            => new CustomHostnameVerifier();

        private sealed class CustomHostnameVerifier : Java.Lang.Object, Javax.Net.Ssl.IHostnameVerifier
        {
            public bool Verify(string hostname, Javax.Net.Ssl.ISSLSession session)
            {
                return Javax.Net.Ssl.HttpsURLConnection.DefaultHostnameVerifier.Verify(hostname, session) ||
                    hostname == "10.0.2.2" && session.PeerPrincipal?.Name == "CN=localhost";
            }
        }
    }
#elif IOS
    public bool IsHttpsLocalhost(NSUrlSessionHandler sender, string url, Security.SecTrust trust)
    {
        if (url.StartsWith("https://localhost"))
            return true;
        return false;
    }
#endif
}

在Android上,GetPlatformMessageHandler方法返回从AndroidMessageHandler派生的CustomAndroidMessageHandler对象。GetPlatformMessageHandler方法将CustomAndroidMessageHandler对象上的ServerCertificateCustomValidationCallback属性设置为一个回调,该回调忽略本地HTTPS开发证书的证书安全检查结果。
在iOS上,GetPlatformMessageHandler方法会传回NSUrlSessionHandler对象,此对象会将其TrustOverrideForUrl属性设定为名为IsHttpsLocalHost的委派,此委派符合NSUrlSessionHandler.NSUrlSessionHandlerTrustOverrideForUrlCallback委派的签章。当URL以https://localhost开头时,IsHttpsLocalHost委派会传回true。
然后,可以将产生的HttpClientHandler对象当做参数传递给两柴组建的HttpClient建构函式:C#语言

#if DEBUG
            HttpsClientHandlerService handler = new HttpsClientHandlerService();
            HttpClient client = new HttpClient(handler.GetPlatformMessageHandler());
#else
            client = new HttpClient();
#endif

然后,在Android模拟器或iOS模拟器中运行的.NET MAUI应用程序可以使用通过HTTPS在本地运行的ASP.NET Core Web服务。

有关如何从Android模拟器和iOS模拟器连接到本地Web服务的详细信息,请查看此链接https://learn.microsoft.com/en-us/dotnet/maui/data-cloud/local-web-services

相关问题