gpt4 book ai didi

java - 如何修复 (SSLException) 收到致命警报 : protocol_version in Java

转载 作者:行者123 更新时间:2023-11-30 08:46:22 25 4
gpt4 key购买 nike

我正在尝试对网站 https://www.facebookbrand.com/ 执行获取调用在这样做的过程中,我收到了错误 (SSLException) Received fatal alert: protocol_version。有问题的网站正在使用 TLSv1.2,如果我设置我的 ConnectionFactory 以专门支持此协议(protocol),它可以正常工作,但我需要它适用于每个网站,并且根据我的理解,将其硬编码为 TLSv1.2 会使它无法工作对于其他不使用 TLSv1.2 的 https 网站。我还尝试包括一个协议(protocol)列表(“TLSv1.2”、“TLSv1.1”、“TLSv1”、“SSLv3”、“SSLv2Hello”),但随后我收到错误 Unrecognized SSL message, plaintext connection。我不关心它有多安全,我只需要能够基本上连接到每个网站,并试图找到最好的方法来做到这一点。下面我包含了我的代码。

这是我设置 httpClient 等的代码:

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslBuilder.build(), SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
PlainConnectionSocketFactory pcsf = new PlainConnectionSocketFactory();
Registry socketFactoryRegistry = RegistryBuilder.create().register("https", sslsf).register("http", pcsf).build();
PoolingHttpClientConnectionManager multiConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
multiConnectionManager.setMaxTotal(100);
multiConnectionManager.setDefaultMaxPerRoute(10);
httpClientBuilder.setConnectionManager(multiConnectionManager);
this.httpClient = httpClientBuilder.disableContentCompression().setSSLSocketFactory(sslsf).build();

下面是通过httpClient获取请求和执行的代码:

HttpGet call = new HttpGet(url);
LinkPullerContentHandler handler = new LinkPullerContentHandler();
PageLinks pl = new PageLinks(url, 200, null);
HttpResponse getResponse;

try {
call.addHeader("User-Agent","Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)");
call.addHeader("Accept","text/html");
call.setConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.IGNORE_COOKIES).build());

try {
getResponse = httpClient.execute(call);
} catch (SocketTimeoutException ste) {
LOG.error(String.format("Socket timeout pulling URL %s; skipping",url));
pl.setHttpStatusCode(408);
return pl;
} catch (ConnectTimeoutException cte) {
LOG.warn(String.format("Connect timeout pulling URL %s; skipping", url));
pl.setHttpStatusCode(408);
return pl;
} catch (UnknownHostException uhe) {
LOG.warn("Unable to resolve host for URL {}; skipping", url);
pl.setHttpStatusCode(404);
return pl;
} catch (Exception e) {
LOG.error(String.format("Unable to load link %s: (%s) %s",
url,e.getClass().getSimpleName(),e.getMessage()),e);
pl.setHttpStatusCode(420);
return pl;
}

int code = getResponse.getStatusLine().getStatusCode();

在尝试专门包含 TLSv1.2 协议(protocol)时,我将 SSLConnectionSocketFactory 设置代码修改为:

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslBuilder.build(),
new String[] { "TLSv1.2" }, null,
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

这适用于有问题的网站,但我觉得它在其他一些网站上会失败,因为它被硬编码为 TLSv1.2。或者,这是我尝试包含其他协议(protocol)时的样子:

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslBuilder.build(),
new String[] { "TLSv1.2", "TLSv1.1", "TLSv1", "SSLv3", "SSLv2Hello"},
null, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

最终得到异常“无法识别的 SSL 消息,纯文本连接。”我还试图包含一个 cipherSuites 列表以查看这是否有帮助,但我还没有取得任何成功。

如果有人能提供任何帮助来帮助我弄清楚如何在不牺牲访问其他站点的能力的情况下完成这项工作,那就太棒了。

提前致谢

最佳答案

不要使用 SSLv2Hello。

该站点显然不支持 v2 格式 hello;即使它会在 v3+ 格式 hello 上成功协商 TLSv1.2,如果我发送(使用 openssl)支持升级到 TLSv1.2(有线版本 3.3)的 v2 格式,它会以明文形式响应 HTML 正文(甚至不是 HTTP header )说“服务不可用”和“网站不可用”。这当然不是 v2 协议(protocol)或 v3+ 协议(protocol)的有效响应。

如果您配置了从 SSLv3 到 TLSv1.2 的所有协议(protocol),但没有配置 SSLv2Hello(无论如何这是 Java8 的默认设置),您将能够与支持低至 SSLv3 的任何内容的其他站点协商,假设没有其他问题,例如该站点使用了无效的证书。 (除了任何实现草案 TLSv1.3 而没有任何标准的网站。)如果有任何服务器仍然存在,太旧或太差,它只支持 SSLv2,Java 无论如何都无法与它通信; SSLv2Hello 的唯一“好处”是 JSSE 抛出一个关于“不支持 SSLv2”的特定异常,而不是更难调试的各种且通常模棱两可的通信错误。

关于java - 如何修复 (SSLException) 收到致命警报 : protocol_version in Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32898488/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com