JDK8版本过高引起MySQL连接失败:javax.net.ssl.SSLHandshakeException: No appropriate protocol

com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure

The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
	at com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174) ~[mysql-connector-java-8.0.17.jar:8.0.17]
	at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64) ~[mysql-connector-java-8.0.17.jar:8.0.17]
	at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:827) ~[mysql-connector-java-8.0.17.jar:8.0.17]
	at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:447) ~[mysql-connector-java-8.0.17.jar:8.0.17]
	at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:237) ~[mysql-connector-java-8.0.17.jar:8.0.17]
	at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:199) ~[mysql-connector-java-8.0.17.jar:8.0.17]
	at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:136) ~[HikariCP-3.2.0.jar:na]
	at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:369) ~[HikariCP-3.2.0.jar:na]
	at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:198) ~[HikariCP-3.2.0.jar:na]
	at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:467) [HikariCP-3.2.0.jar:na]
	at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:541) [HikariCP-3.2.0.jar:na]
	at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:115) [HikariCP-3.2.0.jar:na]
	at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112) [HikariCP-3.2.0.jar:na]
	at com.zaxxer.hikari.HikariDataSource$$FastClassBySpringCGLIB$$eeb1ae86.invoke(<generated>) [HikariCP-3.2.0.jar:na]

一开始以为是网络问题导致的,在寻求帮助后,发现是JDK版本过高导致的:

查看/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/security/java.security(Mac上;Windows同理,在jre/lib/security/java.security里面)发现:

# 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

解决方法一:(破坏安全性)

此处连接的MySQL,导致的报错,修改jdbcUrl,在其后面加useSSL=false后运行正常

解决方法二:(针对MySQL的问题,可以快速解决)

删除SSLv3, TLSv1, TLSv1.1并保存java.security文件,重启项目即可解决问题,删除后此处为:

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

解决方法三:(不推荐)

降低JDK版本。重新安装低版本的JDK。

解决方法四:

碰到类似问题,基本的思路是兼容JDK 8高版本甚至JDK高版本,比如代码层面的:

private Socket overrideTlsProtocol(final Socket socket) {
    if (!(socket instanceof SSLSocket)) {
        throw new RuntimeException("Error, an instance of SSLSocket is expected");
    }
    ((SSLSocket) socket).setEnabledProtocols(new String[]{"SSLv3"});
    return socket;
}

修改为:

private Socket overrideTlsProtocol(final Socket socket) {
    if (!(socket instanceof SSLSocket)) {
        throw new RuntimeException("Error, an instance of SSLSocket is expected");
    }
    ((SSLSocket) socket).setEnabledProtocols(new String[]{"SSLv3", "TLSv1","TLSv1.1"});
    return socket;
}


版权声明:本文为m0_58574228原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。