我想分享一下我在 MAUI .NET 7 应用程序中使用自签名证书发出请求的经验(特别是针对 Android 部分)。
最初的问题来自于使用本机 AndroidMessageHandler 时在 MAUI .NET 7 中未初始化 (null) 的 AndroidMessageHandler.ClientCertificates。
在应用程序中使用自签名证书,并基于 .NET 7 中的 RSA 标准功能生成私钥 (对于 .NET 6,您可以使用 BouncyCastle NuGet 包来存档)
我只能找到一个建议,但没有解决该问题的可行方案 https://github.com/xamarin/xamarin-android/issues/7274 (虽然它是针对 Xamarin Android 的,但对我来说就像点火一样)
因此,为了使其在这里工作,请执行以下步骤:
仅此而已,如果您愿意,我还可以放置一个工作代码
与开发者分享我的经验,因为截至 2023 年比赛还没有可行的解决方案
我有不同的解决方案。
从KeyStore中的链中加载所有证书。
使用 KeyStore 初始化 TrustManagerFactory。
使用 TrustManagerFactory 初始化 SSLContext。
使用该 SSLContext 创建新的 SSLSocketFactory。此过程的关键部分是在创建套接字的方法中注入主机名和地址。
创建Socket,并设置附加参数(Timeout、EnabledProtocols <<< really important, ClientMode, etc...)
握手。
对于 Android,这篇文章 可以做到。
对于iOS,我是这样做的。 在Info.plist中添加
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>YOUR_HOST_HERE</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
在代码中,执行
X509Certificate2 clientCertificate = new X509Certificate2();
try
{
using(Stream cs = await FileSystem.Current.OpenAppPackageFileAsync(YOUR_PEM_FILE_NAME))
{
Byte[] raw = new Byte[cs.Length];
for (Int32 i = 0; i < cs.Length; ++i)
raw[i] = (Byte)cs.ReadByte();
clientCertificate = new X509Certificate2(raw, YOUR_PWD, X509KeyStorageFlags.DefaultKeySet);
}
}
catch(Exception e)
{
//whatever
}
var handler = new NSUrlSessionHandler();
handler.TrustOverrideForUrl = (session, url, trust) =>
{
var uri = new Uri(url);
var ok = uri.Host switch
{
"YOUR_HOST_HERE" => true,
_ => false
};
if (!ok) return false;
trust.SetAnchorCertificates(new X509Certificate2Collection(clientCertificate));
NSError error;
var trustCertificate = trust.Evaluate(out error);
if (error is not null)
{
//whatever
}
return trustCertificate;
};
var httpClient = new (handler);
//Do as usual with the httpClient
请注意,您的 .pem 文件应作为 MauiAsset 位于 Resources/Raw 中。