ASP.NET Core Web API自签名证书HTTPS连接异常求助
ASP.NET Core Web API 自签名证书HTTPS连接异常问题
我正在开发一个ASP.NET Core Web API,需要使用带有密码及关联私钥的自签名证书启用HTTPS。用户可通过应用设置表单上传并配置certificate.crt、certificate.key文件路径,以及证书密码,这些配置会保存至AppSettings.xml。
应用启动后无报错或异常,但访问API端点时返回如下错误:
Error: Client network socket disconnected before a secure TLS connection was established
注:使用CertificateLoader.LoadFromStoreCert()加载证书时,应用运行正常,但业务需求必须支持导入用户自行配置的.crt和.key文件。
2023/11/08 更新
已根据Wiktor Zychla的建议调整代码:
- 配置Kestrel服务器的
SslProtocols为SslProtocols.Tls12 | SslProtocols.Tls13,兼容系统支持的SSL配置 - 新增
LoadCertificate方法,从配置文件读取证书路径和私钥信息 - 新增
SaveCertificate方法,负责安装用户导入的证书、私钥及密码(若存在)
相关代码如下:
Kestrel配置代码
var httpHostBuilder = new WebHostBuilder() .UseKestrel(options => { options.ListenAnyIP(appProperties.ServerPort, listenOptions => { var certificate = HttpServerHandler.LoadCertificate(appProperties); listenOptions.UseHttps(httpsOptions => { httpsOptions.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13; httpsOptions.ServerCertificateSelector = (connectionContext, name) => { if (certificate != null) return certificate; return null; }; }); }); });
证书处理相关代码
public void SaveCertificate() { if (AppProperties.CertFilePath != null && File.Exists(AppProperties.CertFilePath)) certFilePath = AppProperties.CertFilePath; passwordCert = string.IsNullOrEmpty(AppProperties.PasswordCertificate) ? string.Empty : textBoxPasswordCertificate.Texts; if (AppProperties.KeyFilePath != null && File.Exists(AppProperties.KeyFilePath)) keyFilePath = AppProperties.KeyFilePath; var certificate = new X509Certificate2(certFilePath, passwordCert, X509KeyStorageFlags.Exportable); if (!string.IsNullOrEmpty(keyFilePath)) { byte[] privateKeyBytes = File.ReadAllBytes(keyFilePath); using (var privateKeyStream = new MemoryStream(privateKeyBytes)) using (var reader = new StreamReader(privateKeyStream)) { string privateKeyContent = reader.ReadToEnd(); RSA privateKey = RSA.Create(); privateKey.ImportFromPem(privateKeyContent); certificate = certificate.CopyWithPrivateKey(privateKey); } } InstallCertificate(certificate); ConfirmCertificate(certificate); TrustCertificate(certificate.Thumbprint); } public void InstallCertificate(X509Certificate2 certificate) { using (X509Store store = new X509Store(StoreName.Root, StoreLocation.CurrentUser)) { store.Open(OpenFlags.ReadWrite); store.Add(certificate); store.Close(); } using (X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser)) { store.Open(OpenFlags.ReadWrite); store.Add(certificate); store.Close(); } } public void ConfirmCertificate(X509Certificate2 certificate) { using (X509Store store = new X509Store(StoreName.Root, StoreLocation.CurrentUser)) { store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite); store.Certificates.Add(certificate); store.Close(); } using (X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser)) { store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite); store.Certificates.Add(certificate); store.Close(); } } public void TrustCertificate(string certificateThumbprint) { using (X509Store store = new X509Store(StoreName.Root, StoreLocation.CurrentUser)) { try { store.Open(OpenFlags.ReadWrite); X509Certificate2Collection certificates = store.Certificates.Find( X509FindType.FindByThumbprint, certificateThumbprint, validOnly: false); if (certificates.Count > 0) { X509Certificate2 certificate = certificates[0]; X509Chain chain = new X509Chain(); chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.Build(certificate); if (chain.ChainStatus.Length == 0) { Console.WriteLine("Trusted certificate."); } else { Console.WriteLine("Untrusted certificate."); } } else { Console.WriteLine("Certificate not found."); } } finally { store.Close(); } } }
万分感谢,期待进一步协助!顺颂时祺!
内容的提问来源于stack exchange,提问作者Gilberto Júnior
相关产品推荐
相关产品推荐

