Azure Function中HTTP客户端证书配置异常引发SSL握手失败排查
Azure Function中使用KeyVault证书的HTTP客户端SSL握手失败问题
错误信息
结果:函数'MyDummyFunction'调用时引发异常。异常:System.Net.Http.HttpRequestException: 无法建立SSL连接,请查看内部异常。---> System.Security.Authentication.AuthenticationException: 身份验证失败,请查看内部异常。---> Interop+OpenSsl+SslException: SSL握手失败,OpenSSL错误 - SSL_ERROR_SSL。
现有实现代码
public class DummyHttpClient { public readonly HttpClient client; private readonly ILogger<DummyHttpClient> logger; private readonly ActivationConfiguration configuration; public DummyHttpClient(ActivationConfiguration configuration, ILogger<DummyHttpClient> logger) { this.logger = logger; this.configuration = configuration; var handler = ClientHandlerConfigure(); this.client = ClientConfigure(handler); } private HttpClientHandler ClientHandlerConfigure() { var certificate = GetCertificate(); var handler = new HttpClientHandler() { SslProtocols = SslProtocols.Tls12, ClientCertificateOptions = ClientCertificateOption.Manual, ServerCertificateCustomValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) => { return true; }, }; if (certificateForBHN is not null) { handler.ClientCertificates.Add(certificate); } return handler; } private HttpClient ClientConfigure(HttpClientHandler handler) { var client = new HttpClient(handler) { BaseAddress = new Uri(configuration.ApiBaseAddress), Timeout = TimeSpan.FromSeconds(100), }; client.DefaultRequestHeaders.Add("ContentType", "application/json"); client.DefaultRequestHeaders.Add("Accept", "application/json"); client.DefaultRequestHeaders.ConnectionClose = false; return client; } private X509Certificate2 GetCertificate() { var client = new CertificateClient(new Uri($"https://dummykeyvault.vault.azure.net/"), new DefaultAzureCredential()); var certificateOptions = new DownloadCertificateOptions("Activation") { KeyStorageFlags = X509KeyStorageFlags.MachineKeySet, }; var certificate = client.DownloadCertificate(certificateOptions); return certificate.Value; } }
问题排查与修复方案
1. 调整证书存储标志
Azure Function运行在无服务器容器环境中,MachineKeySet依赖机器级密钥存储,容器无对应权限,需替换为内存级存储标志:
var certificateOptions = new DownloadCertificateOptions("Activation") { KeyStorageFlags = X509KeyStorageFlags.EphemeralKeySet | X509KeyStorageFlags.Exportable, };
2. 修正变量名错误
代码中判断证书是否存在的变量certificateForBHN未定义,改为实际获取的certificate变量:
if (certificate is not null) { handler.ClientCertificates.Add(certificate); }
3. 修复请求头设置方式
ContentType不应添加到DefaultRequestHeaders,正确做法是在发送请求时通过请求内容指定:
// 移除错误的ContentType头添加 // client.DefaultRequestHeaders.Add("ContentType", "application/json"); // 发送请求时示例: // var jsonPayload = JsonSerializer.Serialize(data); // var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); // var response = await client.PostAsync("/api/endpoint", content);
4. 验证KeyVault权限与配置
- 确认Azure Function的托管标识(系统/用户分配)拥有KeyVault的
Certificate Get权限 - 检查KeyVault防火墙是否允许Function的出站IP访问
- 确保KeyVault中存储的证书包含完整私钥(需为可导出私钥的证书类型)
5. 移除不安全的SSL验证回调
生产环境中关闭服务器证书验证存在安全风险,建议删除以下代码,恢复默认证书验证逻辑:
// 移除该行代码 ServerCertificateCustomValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) => { return true; },
内容的提问来源于stack exchange,提问作者Wasyster
相关产品推荐
相关产品推荐

