解决 Android 上的 .NET MAUI/Xamarin.AndroidX 应用调用 ASP.NET Core API 端点时 SSL 连接被拒绝的问题

从虚拟机调用本地API报各种 SSL 连接不上的错误,这给本地调试造成了极大的不便,在被这个问题困扰了多日以后,终于在GitHub上找到答案

基于这个 帖子 ,有一个回复

他写了一个帮助类,专门用来调试本地的API,并给出了这个调用类的用法,此帮助类如下

cs 复制代码
using System.Net.Security;

public class DevHttpsConnectionHelper
{
    public DevHttpsConnectionHelper(int sslPort)
    {
        SslPort = sslPort;
        DevServerRootUrl = FormattableString.Invariant($"https://{DevServerName}:{SslPort}");
        LazyHttpClient = new Lazy<HttpClient>(() => new HttpClient(GetPlatformMessageHandler()));
    }

    public int SslPort { get; }

    public string DevServerName =>
#if WINDOWS
        "localhost";
#elif ANDROID
        "10.0.2.2";
#else
        throw new PlatformNotSupportedException("Only Windows and Android currently supported.");
#endif

    public string DevServerRootUrl { get; }

    private Lazy<HttpClient> LazyHttpClient;
    public HttpClient HttpClient => LazyHttpClient.Value;

    public HttpMessageHandler? GetPlatformMessageHandler()
    {
#if WINDOWS
        return null;
#elif ANDROID
        var handler = new CustomAndroidMessageHandler();
        handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
        {
            if (cert != null && cert.Issuer.Equals("CN=localhost"))
                return true;
            return errors == SslPolicyErrors.None;
        };
        return handler;

#else
        throw new PlatformNotSupportedException("Only Windows and Android currently 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";
            }
        }
    }
#endif
}

在安卓机里面是没有 localhost 的,也没有 127.0.0.1 代表本机的取而代之的是 10.0.2.2 。在 HTTPS 里面,证书是被强制使用的,本地 Web API 会有一个默认证书,他里面带一个 "CN=localhost" 所以上面的类针对这个进行了过滤,并且 Android 的底层用的不是默认的 .net 的 HttpClient ,使用了 GetPlatformMessageHandler 进行了重写,这个可是Java 的包。

我的本地调用使用

cs 复制代码
                            var devSslHelper = new DevHttpsConnectionHelper(sslPort: 5001);

                            _blazorHubConnection = new HubConnectionBuilder()
#if ANDROID
                                .WithUrl(devSslHelper.DevServerRootUrl + "/hubs/devicehub"
                                    , configureHttpConnection: o =>
                                    {
                                        o.HttpMessageHandlerFactory = m => devSslHelper.GetPlatformMessageHandler();
                                    }
                                )
#else
            .WithUrl(devSslHelper.DevServerRootUrl + "/hubs/devicehub")
#endif
                                .Build();

这个时候就不报 SSL 的连接错误了,可以方便的正常调试

相关推荐
无所谓จุ๊บ1 个月前
树莓派开发扩展十二 -C#编写客户端控制小车 Xamarin.Forms
c#·xamarin
飞人博尔特的摄影师1 个月前
WPF绑定Bind方法合集,实时更新
visualstudio·c#·wpf·xaml·maui·xamarin·技巧
Rotion_深2 个月前
Xamarin 存档报错 XABLD7000 Xamarin.Tools.Zip.ZipException
xamarin·存档·xabld7000·zipexception
柴可夫司机i3 个月前
.NET MAUI(.NET Multi-platform App UI)下拉选框控件
android·.net·visual studio·xamarin
柴可夫司机i3 个月前
.NET MAUI(.NET Multi-platform App UI)上下文菜单
android·.net·visual studio·xamarin
林晓lx5 个月前
[MAUI 项目实战] 笔记App(二):数据库设计
数据库·maui·xamarin
林晓lx5 个月前
[MAUI 项目实战] 笔记App:程序设计
app·maui·xamarin·.net blazor
大舍传媒6 个月前
波兰媒体海外宣发:波兰媒体投放助力企业在波兰力挽狂澜-大舍传媒
人工智能·科技·microsoft·华为云·harmonyos·xamarin·纳斯达克大屏投放