mysql - 收到致命警报:连接到 MySQL >= 8.0.19 时出现 bad_certificate
问题描述
我尝试通过带有 TLS 的MySQL JDBC 驱动程序(版本 8.0.27)连接到在 docker 中运行的 MySQL 实例。虽然我的设置适用于 8.0.19 之前的所有版本,但对于每个较新版本的连接都失败,并出现以下异常:
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate at
java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131) at
java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
我根据官方文档创建了证书:
# Create CA certificate
openssl genrsa 2048 > ca-key.pem
openssl req -new -x509 -nodes -days 3600 \
-key ca-key.pem -out ca.pem
# Create server certificate, remove passphrase, and sign it
# server-cert.pem = public key, server-key.pem = private key
openssl req -newkey rsa:2048 -days 3600 \
-nodes -keyout server-key.pem -out server-req.pem
openssl rsa -in server-key.pem -out server-key.pem
openssl x509 -req -in server-req.pem -days 3600 \
-CA ca.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem
# Create client certificate, remove passphrase, and sign it
# client-cert.pem = public key, client-key.pem = private key
openssl req -newkey rsa:2048 -days 3600 \
-nodes -keyout client-key.pem -out client-req.pem
openssl rsa -in client-key.pem -out client-key.pem
openssl x509 -req -in client-req.pem -days 3600 \
-CA ca.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem
openssl pkcs12 -export -in client-cert.pem -inkey client-key.pem -out keystore.p12 -name test -CAfile ca.pem -caname root
keytool -importkeystore -deststorepass changeme -destkeypass changeme -destkeystore keystore.jks -srckeystore keystore.p12 -srcstoretype PKCS12 -srcstorepass "" -alias test
我创建了一个设置来验证问题确实只发生在 MySQL 版本 >=8.0.19 上:
public class MySQLTest {
private @Nullable MySQLContainerSSL mySQLContainerSSL;
@AfterEach
void tearDown() {
if (mySQLContainerSSL != null) {
mySQLContainerSSL.stop();
}
}
@ParameterizedTest
@ValueSource(strings = {
"8.0.0",
"8.0.18",
"8.0.19",
"8.0.27"
})
void test(final @NotNull String version) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
mySQLContainerSSL = new MySQLContainerSSL(version);
mySQLContainerSSL.start();
final Properties properties = new Properties();
properties.put("sslMode", "REQUIRED");
properties.put("useSSL", "true");
properties.put("user", mySQLContainerSSL.getPassword());
properties.put("password", mySQLContainerSSL.getUsername());
properties.put("clientCertificateKeyStoreUrl", new File("src/test/resources/mysql/keystore.jks").toURI().toURL().toString());
properties.put("clientCertificateKeyStorePassword", "changeme");
final Connection con = DriverManager.getConnection(mySQLContainerSSL.getJdbcUrl(), properties);
assertNotNull(con);
assertFalse(con.isClosed());
}
public static class MySQLContainerSSL extends MySQLContainer<MySQLContainerSSL> {
public MySQLContainerSSL(final @NotNull String version) {
super(getAdHocImageName(version));
}
@Override
public void stop() {
super.stop();
final String dockerImageName = getDockerImageName();
DockerClientFactory.instance().client().removeImageCmd(dockerImageName).withForce(true).exec();
}
public static @NotNull DockerImageName getAdHocImageName(final @NotNull String mysqlVersion) {
final String s = new ImageFromDockerfile().withDockerfile(Path.of("src/test/resources/mysql/Dockerfile"))
.withBuildArg("MYSQL_VERSION", mysqlVersion)
.get();
return DockerImageName.parse(s).asCompatibleSubstituteFor("mysql");
}
}
}
Dockerfile:
ARG MYSQL_VERSION
FROM mysql:${MYSQL_VERSION}
COPY server-key.pem /var/ssl/server-key.pem
COPY server-cert.pem /var/ssl/server-cert.pem
COPY ca.pem /var/ssl/ca/ca.pem
COPY my.cnf /etc/mysql/my.cnf
COPY my.cnf /var/lib/mysql-files/my.cnf
RUN chown mysql:mysql /etc/mysql/my.cnf \
/var/ssl/ \
/var/ssl/server-key.pem \
/var/ssl/ca/ca.pem \
/var/ssl/server-cert.pem && \
chmod 644 /var/ssl/server-key.pem \
/var/ssl/server-cert.pem \
/var/ssl/ca/ca.pem
我的.cnf:
[mysqld]
ssl_key=/var/ssl/server-key.pem
ssl_cert=/var/ssl/server-cert.pem
ssl_ca=/var/ssl/ca/ca.pem
我的证书似乎是正确的,因为它们适用于旧版本,还是有我没有发现的错误?是否有我不知道的从 8.0.18 到 8.0.19 的行为变化?还有什么我想念的吗?
解决方案
推荐阅读
- angular - 使用 youtube api 和 Angular 搜索电影预告片
- c# - 如何使用 Moq 和 C# 模拟.SingleOrDefault()
- python - 模块导入泡菜行为
- swift - NSWorkspace.shared.icon(forFile:) 不返回图标图像
- javascript - TypeError: _this2 is undefined REACTJS
- python - 可安装包不在 pypi 中
- javascript - array.reduce() 在多个参数上使用索引
- c# - 更新属性时出现 DeviceTwin 问题
- domain-driven-design - 使用值对象验证实体的性能问题
- jquery - Ajax 查询未捕获参考