SSLHandShakeException没有适当的协议

Chr*_*ram 8 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)
Run Code Online (Sandbox Code Playgroud)

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

 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();
    }

}
Run Code Online (Sandbox Code Playgroud)

我已经尝试将我的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) {

    }
}
Run Code Online (Sandbox Code Playgroud)

我很难过,任何帮助将不胜感激!

小智 54

$JRE/lib/security/java.security

jdk.tls.disabledAlgorithms=SSLv3, TLSv1, RC4, DES, MD5withRSA, DH keySize < 1024, \
EC keySize < 224, 3DES_EDE_CBC, anon, NULL
Run Code Online (Sandbox Code Playgroud)

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

我的 Java 版本是“1.8.0_201.

  • @OlegKurbatov 谢谢!它对我的问题有帮助。根据 https://www.oracle.com/java/technologies/javase/8u291-relnotes.html,上周发布的 JDK8-u292 中禁用了 TLS 1.0 和 1.1。您可以尝试在连接字符串中显式使用“enabledTLSProtocols=TLSv1.2”吗?希望它也能帮助您,因为 TLSv1.0 和 TLSv1.1 已弃用。 (19认同)
  • 对于 Java 11+,该文件位于“$JAVA_HOME/conf/security”中。 (8认同)
  • 我的理解不同,这是禁用弱算法,你应该使用更好的算法。 (5认同)
  • 如果有人发现由于 MySQL JDBC 驱动程序错误,您只需从该列表中排除 TLSv1 和 TLSv1.1,它就会起作用。 (5认同)
  • @wwjih123 你能解释一下为什么突然出现这个错误吗?我的解决方案直到今天在 Tomcat9 和 JDK8 上都运行良好,我没有做任何更改,突然我开始收到此错误。不知道为什么?请帮忙 (2认同)

小智 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
Run Code Online (Sandbox Code Playgroud)

我删除TLSv1,并TLSv1.1从列表jdk.tls.disabledAlgorithms里面的文件

/etc/java-8-openjdk/security/java.security

检查后:

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
Run Code Online (Sandbox Code Playgroud)

  • 最新的 openjdk 11 版本(11.0.11+9-0ubuntu2~18.04)也出现该问题。我不明白的是,既然双方似乎都支持TLSv1.2,为什么java和mysql不同意使用TLSv1.2呢?另外,仅仅修补“java.security”文件并不是一个长期的解决方案,这个问题的解决方法是什么? (3认同)

小智 7

就我而言,我正在运行 Centos 8,并且在使用 Imap/Java 时遇到了同样的问题。必须更新系统范围的加密策略级别。

  1. update-crypto-policies --set LEGACY
  2. 重启机器。

就是这样。

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


Ger*_*ser 6

您可以将预期的 TLS 协议添加到您的连接字符串中,如下所示:

jdbc:mysql://localhost:3306/database_name?enabledTLSProtocols=TLSv1.2
Run Code Online (Sandbox Code Playgroud)

那为我解决了问题。


aut*_*ton 5

protocol is disabled or cipher suites are inappropriate
Run Code Online (Sandbox Code Playgroud)

问题的关键在于该陈述。它的基本含义是:

  1. 客户端使用的TLS实现不支持服务器证书使用的密码套件。
  2. 服务器上的TLS配置已禁用客户端支持的密码套件。
  3. 客户端上的TLS配置禁用服务器提供的密码套件。
  4. 客户端和服务器之间的TLS版本不兼容。

这导致TLS中的握手失败,并且连接失败。检查以上三种情况之一或全部。

  • 是的,我不得不在我的“setSecureSocketProtocol”中用“TLS”切换“SSL”并且它工作正常 (2认同)

Gra*_*ray 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));
Run Code Online (Sandbox Code Playgroud)

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

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

-Dcom.ibm.jsse2.overrideDefaultTLS=true
Run Code Online (Sandbox Code Playgroud)


sar*_*ley 5

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

  • 我们遇到了同样的问题,但我们没有完全注释掉“$JRE_HOME/lib/security/java.security”中的“jdk.tls.disabledAlgorithms”行,而是从列表中删除了“TLSv1”和“TLSv1.1”,这足以解决问题。OpenJDK/Oracle 也建议这样做:https://www.oracle.com/java/technologies/javase/8u291-relnotes.html#JDK-8202343 (3认同)