使用async-http-client 2.4.0爬取多域名时遭遇handshake alert错误
解决 AsyncHttpClient 2.4.0 访问特定网站时的
handshake alert: unrecognized_name 错误 这个问题我之前碰到过,本质是SSL握手阶段的SNI(Server Name Indication)兼容性问题:当你的客户端发送SNI扩展(告诉服务器要访问的主机名)时,目标服务器westcommunitycu.org无法识别这个主机名,返回了unrecognized_name警告,但Java的JSSE默认会把这个警告当成致命错误,直接抛出ConnectException。
下面给你几个可行的解决办法,按优先级排列:
1. 临时快速修复(全局生效)
如果你的爬虫只需要处理这个特定网站,或者其他网站不受SNI影响,可以直接添加JVM启动参数:
-Djsse.enableSNIExtension=false
这个参数会全局禁用SNI扩展,客户端不再发送SNI信息,服务器也就不会返回这个警告了。但注意:如果你的爬虫还要访问依赖SNI的多域名服务器(比如一个IP对应多个网站的场景),这个方法可能导致那些网站访问失败。
2. 精准修复(仅针对该客户端/网站)
如果不想全局禁用SNI,可以自定义AsyncHttpClient的SSL配置,让它针对目标网站不发送SNI信息,或者调整SSL参数忽略该警告:
方法A:自定义JDK SSL上下文并禁用SNI
// 创建自定义SSL上下文 SSLContext sslContext = SSLContext.getDefault(); // 配置SSLEngine,禁用SNI SSLEngine engine = sslContext.createSSLEngine(); engine.setUseClientMode(true); SSLParameters sslParams = engine.getSSLParameters(); sslParams.setServerNames(null); // 不发送SNI服务器名称 engine.setSSLParameters(sslParams); // 包装成Netty兼容的SslContext(AsyncHttpClient基于Netty) SslContext nettySslContext = JdkSslContext.forClient() .sslContext(sslContext) .build(); // 构建AsyncHttpClient配置 DefaultAsyncHttpClientConfig config = new DefaultAsyncHttpClientConfig.Builder() .setSslContext(nettySslContext) .build(); AsyncHttpClient client = AsyncHttpClient.create(config);
方法B:通过Netty Channel初始化器调整SslHandler
SslContext sslContext = SslContextBuilder.forClient() .sslProvider(SslProvider.JDK) .build(); DefaultAsyncHttpClientConfig config = new DefaultAsyncHttpClientConfig.Builder() .setSslContext(sslContext) // 添加自定义Channel初始化器,修改SslHandler的SNI设置 .addChannelInitializer(new ChannelInitializer<Channel>() { @Override protected void initChannel(Channel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); SslHandler sslHandler = sslContext.newHandler(ch.alloc()); // 获取SSLEngine并禁用SNI SSLEngine engine = sslHandler.engine(); SSLParameters params = engine.getSSLParameters(); params.setServerNames(null); engine.setSSLParameters(params); pipeline.addLast(sslHandler); } }) .build(); AsyncHttpClient client = AsyncHttpClient.create(config);
3. 长期修复:升级AsyncHttpClient
AsyncHttpClient 2.4.0是比较旧的版本(2018年发布),后续版本(比如2.12.x及以上)对SNI的兼容性做了优化,可能已经修复了把unrecognized_name警告当成致命错误的问题。建议升级到最新稳定版本,既能解决这个问题,还能获得更多安全补丁和性能提升。
内容的提问来源于stack exchange,提问作者user8520666
相关产品推荐
相关产品推荐

