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

Apache Async Http Client通过IP连接时自定义SNI服务器名配置问题

为Apache Async Http Client 4.1.3通过IP连接时配置SNI信息

当你需要通过IP地址连接HTTPS服务,同时指定SNI(Server Name Indication)信息确保SSL握手获取正确证书时,可以通过自定义SSLIOSessionStrategy实现,以下是具体步骤:

核心思路

Apache Async Http Client默认会在使用域名连接时自动处理SNI,但直接用IP连接时不会主动设置。我们需要重写SSLIOSessionStrategy的createSSLEngine方法,手动为SSLEngine添加SNI主机名参数,模拟openssl s_client -connect 1.2.3.4:443 -servername ab.cd.com的行为。

实现代码

1. 自定义SNI SSL会话策略

import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SNIHostName;
import java.util.Collections;

public class CustomSNISSLIOSessionStrategy extends SSLIOSessionStrategy {

    private final String sniServerName;

    public CustomSNISSLIOSessionStrategy(SSLContext sslContext, String sniServerName) {
        super(sslContext);
        this.sniServerName = sniServerName;
    }

    @Override
    public SSLEngine createSSLEngine(String host, int port) {
        SSLEngine sslEngine = super.createSSLEngine(host, port);
        SSLParameters sslParams = sslEngine.getSSLParameters();
        // 设置SNI主机名,对应openssl的-servername参数
        sslParams.setServerNames(Collections.singletonList(new SNIHostName(sniServerName)));
        sslEngine.setSSLParameters(sslParams);
        return sslEngine;
    }
}

2. 构建带SNI配置的异步HTTP客户端

import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.nio.reactor.IOReactorException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLContexts;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;

public class AsyncHttpClientSNIDemo {

    public static CloseableHttpAsyncClient createSNIEnabledClient(String sniServerName) 
            throws IOReactorException, NoSuchAlgorithmException, KeyManagementException {
        
        // 创建默认SSLContext,如需自定义证书信任可替换为自己配置的SSLContext
        SSLContext sslContext = SSLContexts.createDefault();
        
        // 初始化自定义SNI策略
        CustomSNISSLIOSessionStrategy sslStrategy = new CustomSNISSLIOSessionStrategy(sslContext, sniServerName);
        
        // 配置连接管理器,传入自定义SSL策略
        PoolingNHttpClientConnectionManager connManager = new PoolingNHttpClientConnectionManager(
                new DefaultConnectingIOReactor(),
                null,
                sslStrategy,
                null);
        
        // 构建并返回异步客户端
        return HttpAsyncClients.custom()
                .setConnectionManager(connManager)
                .build();
    }

    public static void main(String[] args) throws Exception {
        // 替换为目标服务的SNI域名
        String targetSNIName = "ab.cd.com";
        CloseableHttpAsyncClient client = createSNIEnabledClient(targetSNIName);
        
        client.start();
        // 发起请求时直接使用IP地址,示例:HttpGet request = new HttpGet("https://1.2.3.4:443/api");
        // ... 执行请求逻辑 ...
        client.close();
    }
}

关键说明

  • 自定义策略通过SSLParameters.setServerNames方法添加SNI主机名,确保SSL握手时携带该信息,服务器据此返回对应域名的证书。
  • 连接管理器初始化时传入自定义SSL策略,所有通过该管理器创建的连接都会自动应用SNI配置。
  • 发起请求时直接使用IP地址作为目标URL即可,无需修改请求地址中的主机名。

内容的提问来源于stack exchange,提问作者abs060

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 05:07:17