SSLHandShakeException没有适当的协议

时间:2016-07-05 14:24:35

标签: java ssl bufferedreader

我最近在我的网站上添加了SSL,可以通过https访问。现在,当我的java应用程序尝试向我的网站发出请求并使用缓冲读取器从中读取时,它会生成此堆栈跟踪

我没有使用自签名证书,证书来自Namecheap,他使用COMODO SSL作为CA来签署我的证书。即时通讯使用java 8

javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
at sun.security.ssl.Handshaker.activate(Handshaker.java:503)
at sun.security.ssl.SSLSocketImpl.kickstartHandshake(SSLSocketImpl.java:1482)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1351)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)

我的代码非常基本,只是尝试使用缓冲的阅读器阅读我网站上的页面

 private void populateDataList() {
    try {
        URL url = new URL("https://myURL.com/Data/Data.txt");
        URLConnection con = url.openConnection();
        con.setRequestProperty("Connection", "close");
        con.setDoInput(true);
        con.setUseCaches(false);

        BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
        String line;
        int i = 0;
        while((line = in.readLine()) != null) {
            this.url.add(i, line);
            i++;
        }
    }   catch (Exception e) {
        e.printStackTrace();
    }

}

我尝试将我的SSL证书添加到JVM的密钥库中,我甚至尝试使用此代码接受每个证书(这证明了我所知道的SSL的目的)

 private void trustCertificate() {
    TrustManager[] trustAllCerts = new TrustManager[] {
            new X509TrustManager() {
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }
                public void checkClientTrusted(
                        java.security.cert.X509Certificate[] certs, String authType) {
                }
                public void checkServerTrusted(
                        java.security.cert.X509Certificate[] certs, String authType) {
                }
            }
    };
    try {
        SSLContext sc = SSLContext.getInstance("TLS");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    } catch (GeneralSecurityException e) {
    }
    try {
        URL url = new URL("https://myURL.com/index.php");
        URLConnection con = url.openConnection();
        BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
        String line;
        while((line = br.readLine()) != null) {
            System.out.println(line);
        }

    } catch (Exception e) {

    }
}

我很难过,任何帮助都会非常感激!

12 个答案:

答案 0 :(得分:31)

我也在 ubuntu 18.04 上的 Java8 更新 1.8.0.229 上遇到了这个问题 我更改了以下内容

# Example:
#   jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
#jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \
#    DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
#    include jdk.disabled.namedCurves

jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, \
    DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
    include jdk.disabled.namedCurves

从文件 /etc/java-8-openjdk/security/java.security 中删除如上所示的 TLSv1 和 TLSv1.1

检查后:

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 28
Server version: 5.7.33-0ubuntu0.18.04.1 (Ubuntu)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> SHOW GLOBAL VARIABLES LIKE 'tls_version';
+---------------+-----------------------+
| Variable_name | Value                 |
+---------------+-----------------------+
| tls_version   | TLSv1,TLSv1.1,TLSv1.2 |
+---------------+-----------------------+
1 row in set (0.00 sec)

mysql> exit

答案 1 :(得分:5)

就我而言,我是Centos 8运行者,并且Imap / Java也有同样的问题。 必须更新系统范围的密码策略级别。

  1. update-crypto-policies --set LEGACY
  2. 重新启动计算机。

就这样。

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/considerations_in_adopting_rhel_8/security_considerations-in-adopting-rhel-8#tls-v10-v11_security

答案 2 :(得分:5)

<块引用>

javax.net.ssl.SSLHandshakeException: 没有合适的协议(协议被禁用或密码套件不合适)

为了后代,我最近使用 IBM 的 JDK8 实现遇到了这个问题,默认情况下它专门禁用了 TLS1.1 和 1.2(原文如此)。如果您想查看 JVM 支持哪些 TLS 版本,请运行如下代码:

SSLContext context = SSLContext.getInstance("TLS");
context.init(null, null, null);
String[] supportedProtocols = context.getDefaultSSLParameters().getProtocols();
System.out.println(Arrays.toString(supportedProtocols));

代码在 AIX JDK8 下默认吐出 [TLSv1]。不好。在 Redhat 和 Solaris 下,它吐出 [TLSv1, TLSv1.1, TLSv1.2]

我在 java.security 文件中找不到任何值来解决此问题,但可能有一些适用于您的架构。在 IBM 特定案例中,我们必须添加:

-Dcom.ibm.jsse2.overrideDefaultTLS=true

答案 3 :(得分:5)

我们在升级到 jre1.8.0_291 后开始遇到这个问题。我注释掉了“jdk.tls.disabledAlgorithms=SSLv3、TLSv1、TLSv1.1、RC4、DES、MD5withRSA、
DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL,
在位于 C:\Program Files\Java\jre1.8.0_291\lib\security 的 java.security 中包含 jdk.disabled.namedCurves" 解决了问题。

答案 4 :(得分:4)

协议已禁用或密码套件不合适
问题的关键在于该陈述。它基本上意味着:

  1. 客户端使用的TLS实现不支持服务器证书使用的密码套件。
  2. 服务器上的TLS配置已禁用客户端支持的密码套件。
  3. 客户端上的TLS配置禁用服务器提供的密码套件。
  4. 客户端和服务器之间的TLS版本不兼容。
  5. 这会导致TLS中的握手失败,并且连接失败。检查上述三种情况中的一种或全部。

答案 5 :(得分:4)

您可以像这样将预期的 TLS 协议添加到您的连接字符串中:

jdbc:mysql://localhost:3306/database_name?enabledTLSProtocols=TLSv1.2

这为我解决了问题。

答案 6 :(得分:3)

$JRE/lib/security/java.security中:

jdk.tls.disabledAlgorithms=SSLv3, TLSv1, RC4, DES, MD5withRSA, DH keySize < 1024, \
EC keySize < 224, 3DES_EDE_CBC, anon, NULL

启用此行,在我注释掉该行之后,一切正常。显然在jre1.8.0_181之后/之中,启用了此行。

我的Java版本是“ 1.8.0_201。

答案 7 :(得分:2)

我遇到过

javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)

从 Java 11 应用程序访问启用 TLS 1.3 的端点时出错。例如,这是 GCP 中的常见情况。

只需从 Java 11 升级到 Java 14,问题就消失了,我的代码没有任何更改。

Java 11 默认不弃用早期的 TLS 协议版本。简单地将运行时升级到 Java 14,而不是对其进行配置。

答案 8 :(得分:2)

就我而言,我不得不将 mysql 客户端库升级到最新版本,然后它又开始工作了:

    <dependency>
       <groupId>mysql</groupId>
       <artifactId>mysql-connector-java</artifactId>
       <version>8.0.24</version>
    </dependency>

答案 9 :(得分:1)

很显然,如果您禁用了TLS 1.0,则不会发送电子邮件。 TLS版本1.1和1.2不起作用。彼得的建议对我有用。

答案 10 :(得分:0)

对于这种情况下的我:

javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)

我发现这是与 JDK/JRE (Java\jdk1.8.0_291\jre\lib\security) 配置相关的,为了解决它,您需要禁用 TLS anon 和 NULL 密码套件.

您可以在此处的官方文档中找到如何执行此操作: https://www.java.com/en/configure_crypto.html

此外,在执行此操作之前,请考虑使用 LEGACY 算法的影响。

答案 11 :(得分:0)

我在tomcat7服务器上遇到了同样的情况,5.7.34-0ubuntu0.18.04.1,openjdk版本“1.8.0_292”

我尝试了很多方法,例如在 server.xml 文件中禁用 SSL、更改连接字符串等

但最后我所做的只是编辑文件 java.security 须藤纳米/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/security/java.security

注释掉并删除 TLSv1 和 TLSv1.1

# Comment the line below
#jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \
#    DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
#    include jdk.disabled.namedCurves

# your new line should read as beloew
jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, \
DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
include jdk.disabled.namedCurves