You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 21:35:14