最近碰到个JDBC连接MySQL出现SSL错误的问题。

SSL(Secure Socket Layer:安全套接字层),利用数据加密、身份验证和消息完整性验证机制,为基于TCP等可靠连接的应用层协议提供安全性保证。

SSL协议提供的功能主要有,

1. 数据传输的机密性:利用对称密钥算法对传输的数据进行加密。

2. 身份验证机制:基于证书利用数字签名方法对服务器和客户端进行身份验证,其中客户端的身份验证是可选的。
3. 消息完整性验证:消息传输过程中使用MAC算法来检验消息的完整性。

如果用户的传输不是通过SSL的方式,那么其在网络中数据都是以明文进行传输的,而这给别有用心的人带来了可乘之机。所以,现在很多大型网站都开启了SSL功能。同样地,在我们数据库方面,如果客户端连接服务器获取数据不是使用SSL连接,那么在传输过程中,数据就有可能被窃取。

前几天同事碰到了和这个相关的问题,MySQL 5.6如下两个SSL相关的参数默认值是DISABLED,

MySQL 5.7如下两个SSL相关的参数默认值是YES,

客户端通过如下这个jdbc串连接MySQL 5.6,没问题,

jdbc:mysql://x.x.x.x:3306/test?characterEncoding=utf8

但是如果连接MySQL 5.7,提示如下警告,

WARN: Establishing SSL connection without server's identity verification is not recommended.
According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set.
For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'.
You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.

如果增加useSSL=false,执行是正常的,

jdbc:mysql://x.x.x.x:3306/test?characterEncoding=utf8&useSSL=false

如果改为useSSL=true,

jdbc:mysql://x.x.x.x:3306/test?characterEncoding=utf8&useSSL=true

则会执行错误,

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failureThe last packet successfully received from the server was 239 milliseconds ago.  The last packet sent successfully to the server was 235 milliseconds ago.at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)at java.lang.reflect.Constructor.newInstance(Constructor.java:408)at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:990)at com.mysql.jdbc.ExportControlled.transformSocketToSSLSocket(ExportControlled.java:201)at com.mysql.jdbc.MysqlIO.negotiateSSLConnection(MysqlIO.java:4914)at com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(MysqlIO.java:1663)at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1224)at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2199)at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2230)at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2025)at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:778)at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:47)at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)at java.lang.reflect.Constructor.newInstance(Constructor.java:408)at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:386)at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:330)at java.sql.DriverManager.getConnection(DriverManager.java:664)at java.sql.DriverManager.getConnection(DriverManager.java:247)at com.test.TestMySQL.main(TestMySQL.java:37)
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchorsat sun.security.ssl.Alerts.getSSLException(Alerts.java:192)at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1937)at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1478)at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:212)at sun.security.ssl.Handshaker.processLoop(Handshaker.java:957)at sun.security.ssl.Handshaker.process_record(Handshaker.java:892)at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1050)at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363)at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391)at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1375)at com.mysql.jdbc.ExportControlled.transformSocketToSSLSocket(ExportControlled.java:186)... 18 more
Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchorsat com.mysql.jdbc.ExportControlled$X509TrustManagerWrapper.checkServerTrusted(ExportControlled.java:302)at sun.security.ssl.AbstractTrustManagerWrapper.checkServerTrusted(SSLContextImpl.java:922)at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1460)... 26 more
Caused by: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchorsat sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:153)at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:79)at java.security.cert.CertPathValidator.validate(CertPathValidator.java:292)at com.mysql.jdbc.ExportControlled$X509TrustManagerWrapper.checkServerTrusted(ExportControlled.java:295)... 28 more

根本原因还是MySQL 5.7提高了安全连接的要求,MySQL 5.6中默认关闭SSL,因此客户端连接,不指定useSSL没事儿,但是连接MySQL 5.7,因为默认SSL打开的,所以在jdbc中未指定useSSL会提示个warning,如果在jdbc中指定useSSL=false,明确不使用SSL连接,自然没问题,但如果使用useSSL=true,是强制使用SSL连接,然而这个不仅要求数据库端ssl配置打开,还需要在客户端做一些SSL的配置,我没操作过,各位自行搜索。

如果服务器端安装了SSL,可以在data_dir中看到自动生成的如下文件,

ca.pem            -- 自签的CA证书,客户端连接也需要提供
server-key.pem    -- 服务器端私钥文件
server-cert.pem   -- 服务器端证书文件
client-key.pem    -- 客户端连接服务器端需要提供的私钥文件
client-cert.pem   -- 客户端连接服务器端需要提供的证书文件
public_key.pem    -- 私钥/公钥对的共有成员
private_key.pem   -- 私钥/公钥对的私有成员

如果用户是采用本地localhost或者socket连接数据库,那么不会使用SSL方式了,可以用\s显示当前的连接状态,如下所示,本地连接,当前连接没有在SSL安全连接中,SSL是not in use,

mysql> \s
--------------
mysql  Ver 14.14 Distrib 5.7.32, for el7 (x86_64) using  EditLine wrapperConnection id:          7939
Current database:
Current user:           root@localhost
SSL:                    Not in use
Current pager:          stdout
Using outfile:          ''
Using delimiter:        ;
Server version:         5.7.32-log MySQL Community Server (GPL)
Protocol version:       10
Connection:             Localhost via UNIX socket
Server characterset:    utf8mb4
Db     characterset:    utf8mb4
Client characterset:    utf8
Conn.  characterset:    utf8
UNIX socket:            /tmp/mysql.sock
Uptime:                 104 days 5 hours 30 min 3 secThreads: 7  Questions: 287208  Slow queries: 30  Opens: 4496  Flush tables: 8  Open tables: 1393  Queries per second avg: 0.031
--------------

如果用SSL,因为牵扯到加密的操作,对性能就可能产生一些影响,借鉴这篇博文,提供的测试数据,了解一下。测试中的服务器配置,CPU是32核心,内存是128G,SSD磁盘。为了尽量准确测试QPS,采用全内存查询,因为我们线上热点数据基本都在内存中,按照并发线程数分类:1线程、4线程、8线程、16线程、24线程、32线程、64线程,

P.S. https://www.cnblogs.com/mysql-dba/p/7061300.html

测试数据如下,

从测试数据可以发现,开启SSL后,数据库QPS平均降低了23%左右,相对还是比较影响性能的。从SSL实现方式来看,建立连接时需要进行握手、加密、解密等操作,所以耗时基本都在建立连接阶段,这对于使用短连接的应用程序可能产生更大的性能损耗,不过如果使用连接池或者长连接可能会好许多。

因此,是否采用SSL,取决于系统的安全等级和性能要求,

1. 对于非常敏感核心的数据,或者QPS本来就不高的核心数据,可以采用SSL方式保障数据安全性。

2. 对于采用短连接、要求高性能的应用,或者不产生核心敏感数据的应用,性能和可用性才是首要,建议不要采用SSL方式。

近期更新的文章:

《优雅编写SQL的几个案例》

《优化前置思想的成本收益关系》

《v$视图存储SQL的bug》

《RPO和RTO是什么?》

《Linux的inode是什么?》

文章分类和索引:

《公众号800篇文章分类和索引》

JDBC SSL连接MySQL相关推荐

  1. JDBC SSL连接SQL Server

    上次碰到的是<JDBC SSL连接MySQL>,这次则是SSL连接SQL Server. 最近同事的一套系统,需要通过druid同时连接SQL Server 2008和SQL Server ...

  2. JDBC使用SSL连接mysql(包含ssl_type=x509)

    前言 因为工作中上层领导发话,保密级别高的数据库交互需要用SSL连接,然后集体懵逼了,都没有弄过,问过自己的朋友也都没搞过这些,网上找的案例总是失败,最后参照MySql官网终于打通了x509的连接,接 ...

  3. 【JDBC】连接MySQL数据库实现增删改查

    文章目录 一.JDBC编写步骤 二.数据库连接--Connection 2.1 连接要素 2.1.1 Driver接口实现类 2.1.2 URL 2.1.3 用户名和密码 2.2 建立连接 2.2.1 ...

  4. JDBC: Java连接MySQL

    文章目录 一.Java连接MySQL数据库步骤 二.JDBC基本操作:CRUD 2.1 Statement 2.2 ResultSet 之滚动结果集(了解) 2.3 示例: 查询用户 2.4 DBUt ...

  5. 数据库编程连接mysql_使用JDBC编程-连接MySQL数据库

    作者:李老师,吕老师              2019-09-23 准备工作: 1.首先安装MySQL5.5.30 64位:链接:https://pan.baidu.com/s/1H99PH-jRq ...

  6. Android Studio使用JDBC远程连接mysql的注意事项(附示例)

    JDBC为java程序访问各种类型的关系型数据库提供了统一的接口,用户不必针对不同数据库写出不同的代码,但是使用JDBC必须得下载相应的驱动,比如我这里是要连接mysql,于是就到mysql官网去下载 ...

  7. android studio用mysql_Android Studio使用JDBC远程连接mysql的注意事项(附示例)

    JDBC为java程序访问各种类型的关系型数据库提供了统一的接口,用户不必针对不同数据库写出不同的代码,但是使用JDBC必须得下载相应的驱动,比如我这里是要连接mysql,于是就到mysql官网去下载 ...

  8. JDBC——java连接mysql、hive、hbase教程

    JDBC模板 一.准备工作 1.1.创建Maven工程 1.2.修改pom文件 1.3.修改Project Structure 1.4.修改Settings 1.5.资源文件夹 二.Java连接mys ...

  9. 处理ssl连接MySQL问题方法

    1. 检查当前SSL / TLS状态 我们将使用-h指定IPv4本地环回接口,以强制客户端与TCP连接,而不是使用本地套接字文件. 这将允许我们检查TCP连接的SSL状态: mysql -u root ...

最新文章

  1. USANavyElectronicsCourse-Excerlent
  2. 微信小程序:获取地理定位和显示相应的城市名称。
  3. 2021廊坊高考口试成绩查询,2021河北八省联考成绩查询入口
  4. Java 只读集合
  5. java查询F分布表
  6. Centos修复boot分区
  7. 大学计算机课程教学建议,计算机应用基础课程教学的建议
  8. Spring boot 整合Druid框架不支持瀚高,报dbtype not support
  9. onnx-modifier:ONNX可视化编辑
  10. 基于 Squid 实现爬虫代理服务
  11. ISE中如何将自己的verilog源代码.v或VHDL源代码.vhd封装打包成IP核?
  12. 新加坡环球影城:新加坡亲子游一日游好去处
  13. 数据拯救单身狗!助攻两性相处的6个小数据
  14. 中国大学moocpython_中国大学MOOC(慕课)_Python 语言程序设计_测试题及答案
  15. 研究显示每天工作超8小时得心脏病概率增加80%,生命很重要,工作不要那个累。...
  16. python中global什么意思_python中的global关键字的使用方法
  17. JVM(八)--关于反射
  18. 用Python爬取陈奕迅歌曲10万条评论的新发现
  19. swift篇 基础知识5 -- 字符串(String)和字符(character)
  20. 链表实现栈 FILO

热门文章

  1. MySQL常规篇之增删改查(精选)
  2. 数据分析报告结构规范设计
  3. PAT乙级 ——开学寄语
  4. 计算机电源多低无法使用吗,怎么确定电脑电源供电不足?
  5. 30ea什么意思_ea阶段是什么?你未必全知道!
  6. GD32官方固件库(标准外设库)下载
  7. Python实现基于负熵最大判据的FastICA胎心信号分离
  8. Linux系统Centos7的虚拟机安装
  9. syzlang语法编写案例学习 —— Looking for Remote Code Execution bugs in the Linux kernel
  10. [分享]SQl语句学习专题