简体   繁体   English

如何修复 (SSLException) 收到致命警报:Java 中的协议版本

[英]How to fix (SSLException) Received fatal alert: protocol_version in Java

I'm attempting to execute a get call to the website https://www.facebookbrand.com/ and in doing so I'm receiving the error (SSLException) Received fatal alert: protocol_version.我正在尝试对网站https://www.facebookbrand.com/执行 get 调用,这样做时我收到错误 (SSLException) 收到致命警报:protocol_version。 The website in question is using TLSv1.2 and if I setup my ConnectionFactory to specifically support this protocol only it works fine, but I need it to work for every website and from my understanding hard coding it to TLSv1.2 would make it not work for other https websites that don't use TLSv1.2.有问题的网站正在使用 TLSv1.2,如果我将 ConnectionFactory 设置为专门支持此协议,则它只能正常工作,但我需要它适用于每个网站,并且根据我的理解,将其硬编码为 TLSv1.2 会使它不起作用对于其他不使用 TLSv1.2 的 https 网站。 I also tried including a list of protocols ("TLSv1.2", "TLSv1.1", "TLSv1", "SSLv3", "SSLv2Hello") but then I get the error Unrecognized SSL message, plaintext connection.我还尝试包含一个协议列表(“TLSv1.2”、“TLSv1.1”、“TLSv1”、“SSLv3”、“SSLv2Hello”),但随后我收到错误 Unrecognized SSL message, plaintext connection 。 I don't care about how secure it is I just need to be able to connect to every website essentially and am trying to find the best way to do this.我不在乎它有多安全,我只需要能够基本上连接到每个网站,并且正在尝试找到最好的方法来做到这一点。 Below I have included my code.下面我已经包含了我的代码。

Here's my code for setting up the httpClient etc:这是我用于设置 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();

Here's the code for the get request and execution via httpClient:下面是通过 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();

In attempting to include specifically the TLSv1.2 protocol I modified the SSLConnectionSocketFactory setup code to this:在尝试特别包含 TLSv1.2 协议时,我将 SSLConnectionSocketFactory 设置代码修改为:

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

Which works for the website in question but I feel like it would fail on some others since it's hard coded to TLSv1.2.这适用于有问题的网站,但我觉得它会在其他网站上失败,因为它硬编码为 TLSv1.2。 Alternatively here was how it looked when I tried including additional protocols:或者,这是我尝试包含其他协议时的样子:

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

Which ends up getting the exception "Unrecognized SSL message, plaintext connection."最终得到异常“无法识别的 SSL 消息,纯文本连接”。 I am also attempting to include a list of cipherSuites to see if this helps but I haven't had any success with it yet.我还试图包含一个 cipherSuites 列表,看看这是否有帮助,但我还没有取得任何成功。

Any help someone can provide to help me figure out how to make this work while not sacrificing being able to get other sites would be awesome.有人可以提供任何帮助来帮助我弄清楚如何在不牺牲能够访问其他站点的情况下完成这项工作,这将很棒。

Thanks in advance提前致谢

Don't use SSLv2Hello.不要使用 SSLv2Hello。

That site apparently doesn't support v2 format hello;该站点显然不支持 v2 格式你好; even though it will successfully negotiate TLSv1.2 on a v3+ format hello, if I send (with openssl) v2 format supporting upgrade to TLSv1.2 (wire version 3.3), it responds with an HTML body (not even HTTP headers) in plaintext saying "Service unavailable" and "Site unavailable".即使它会在 v3+ 格式上成功协商 TLSv1.2,如果我发送(使用 openssl)v2 格式支持升级到 TLSv1.2(有线版本 3.3),它会以纯文本形式响应 HTML 正文(甚至不是 HTTP 标头)说“服务不可用”和“站点不可用”。 That is of course not a valid response for either v2 protocol or v3+ protocols.这当然不是 v2 协议或 v3+ 协议的有效响应。

If you configure all protocols from SSLv3 through TLSv1.2 but not SSLv2Hello -- which is the default for Java8 anyway -- you will be able to negotiate with other sites that support anything down to SSLv3, assuming no other problem, like the site uses an invalid cert.如果您配置了从 SSLv3 到 TLSv1.2 的所有协议,但没有配置 SSLv2Hello——无论如何这是 Java8 的默认设置——您将能够与支持任何低至 SSLv3 的任何其他站点进行协商,假设没有其他问题,如该站点使用无效的证书。 (And excepting any site that implements only draft TLSv1.3 and nothing standard.) If there is any server still out there so old or lame it supports only SSLv2, Java can't actually communicate with it anyway; (并且除了任何实现 TLSv1.3 草案而没有任何标准的站点。)如果仍然有任何服务器如此陈旧或蹩脚,它仅支持 SSLv2,Java 无论如何实际上无法与其通信; the only "benefit" of SSLv2Hello is that JSSE throws a specific exception about "SSLv2 not supported" rather than varied and often ambiguous comms errors that are harder to debug. SSLv2Hello 的唯一“好处”是 JSSE 抛出关于“不支持 SSLv2”的特定异常,而不是更难调试的各种且通常不明确的通信错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在java中设置SSL协议版本? 我怎么知道是哪一个? javax.net.ssl.SSLException:收到致命警报:protocol_version - How do I set SSL protocol version in java? And how do I know which one? javax.net.ssl.SSLException: Received fatal alert: protocol_version javax.net.ssl.SSLException:收到致命警报:Selenium的protocol_version - javax.net.ssl.SSLException: Received fatal alert: protocol_version with Selenium 调用 Web 服务:javax.net.ssl.SSLException:收到致命警报:protocol_version - Calling web service: javax.net.ssl.SSLException: Received fatal alert: protocol_version javax.net.ssl.SSLException:收到致命警报:协议版本 - javax.net.ssl.SSLException: Received fatal alert: protocol_version Android Studio 抛出“线程“main”中的异常 javax.net.ssl.SSLException:收到致命警报:protocol_version” - Android Studio throwing "Exception in thread "main" javax.net.ssl.SSLException: Received fatal alert: protocol_version" 获取 javax.net.ssl.SSLException:在使用 Jsoup 抓取数据时收到致命警报:protocol_version - getting javax.net.ssl.SSLException: Received fatal alert: protocol_version while scraping data using Jsoup 收到致命警报:protocol_version 构建失败 Gradle/Maven - Received fatal alert: protocol_version build failure Gradle/Maven Apache Karaf - 收到致命警报:protocol_version - Apache Karaf - Received fatal alert: protocol_version 无法使用 maven web 项目在 Z69F0F6923BC1F8AAA26B96BCZ 项目中创建新的 java 因收到致命警报协议2: - Can not to create new java with maven web project in NetBeans due Received fatal alert: protocol_version 我该如何解决-无法下载mysql连接器.jar ...收到致命警报:protocol_version? - How could I solve - Failed to download mysql connector .jar… Received fatal alert: protocol_version?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM