gpt4 book ai didi

java - 禁用 JDBC 连接上的 keystore

转载 作者:行者123 更新时间:2023-12-01 14:30:22 24 4
gpt4 key购买 nike

我有一个使用 ConnectorJ 连接到 MySQL 数据库的应用程序,没有出现任何问题。但是,我现在需要扩展应用程序以针对其他端点执行相互验证的 HTTP 请求。

我的问题是,为 HTTP 请求定义客户端 keystore 似乎会导致该 keystore 也在 JDBC 连接中使用。 MySQL 数据库不需要提供证书,因此握手失败,如下所示。

来源(简化)

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class DbTester {

private static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
private static final String JDBC_URL = "jdbc:mysql://XXX.XXX.XXX.XXX/mysql?useSSL=true";
private static final String JDBC_USERNAME = "xxxxxxxxxx";
private static final String JDBC_PASSWORD = "xxxxxxxxxx";

public static void main(final String[] args) throws Exception {

Class.forName(JDBC_DRIVER);
Connection connection = DriverManager.getConnection(JDBC_URL, JDBC_USERNAME, JDBC_PASSWORD);

try (PreparedStatement statement = connection.prepareStatement("select 1 from user")){
try (ResultSet results = statement.executeQuery()) {
if (results.next()) {
System.out.println("Query Result: " + results.getString(1));
}
}
}
}
}

示例

健全性测试运行(成功输出):

> java -cp .:mysql-connector-java-5.1.24-bin.jar DbTester
Query Result: 1

生成任意 key :

keytool -genkey -keyalg RSA -keystore myKeystore.jks -storepass password

使用指定的 key 重新运行(失败!!):

java -cp .:mysql-connector-java-5.1.24-bin.jar -Djavax.net.ssl.keyStore=myKeystore.jks -Djavax.net.ssl.keyStorePassword=password DbTester

Exception in thread "main" com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet successfully received from the server was 911 milliseconds ago. The last packet sent successfully to the server was 907 milliseconds ago.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
...
Caused by: javax.net.ssl.SSLException: Unsupported record version Unknown-0.0
at sun.security.ssl.InputRecord.readV3Record(InputRecord.java:524)
at sun.security.ssl.InputRecord.read(InputRecord.java:509)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:927)
at sun.security.ssl.SSLSocketImpl.waitForClose(SSLSocketImpl.java:1707)
at sun.security.ssl.HandshakeOutStream.flush(HandshakeOutStream.java:122)
at sun.security.ssl.Handshaker.sendChangeCipherSpec(Handshaker.java:972)
at sun.security.ssl.ClientHandshaker.sendChangeCipherAndFinish(ClientHandshaker.java:1087)
at sun.security.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.java:1006)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:285)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:868)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:804)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1016)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1323)
at com.mysql.jdbc.ExportControlled.transformSocketToSSLSocket(ExportControlled.java:90)
... 17 more

版本

java版本“1.7.0_21”Java(TM) SE 运行时环境(版本 1.7.0_21-b11)Java HotSpot(TM) 64 位服务器 VM(内部版本 23.21-b01,混合模式)

mysql服务器:5.1.66-log源码​​分布

connectorj:mysql-connector-java-5.1.24-bin.jar

编辑/已解决

我通过显式加载 HTTP 连接的证书(并删除 JVM 级环境参数)来实现此目的:

        String certPath = System.getProperty("my.cert.path");
String certPassword = System.getProperty("my.cert.password");

in = new FileInputStream(new File(certPath));
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(in, certPassword.toCharArray());
in.close();

KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, certPassword.toCharArray());
KeyManager[] keymanagers = kmf.getKeyManagers();

SSLContext context = SSLContext.getInstance("TLS");
context.init(keymanagers, null, null);
SSLSocketFactory sslSocketFactory = context.getSocketFactory();

HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(sslSocketFactory);
// do HTTP connection OPS :)

最佳答案

我通过显式加载 HTTP 连接的证书(并删除 JVM 级环境参数)来实现此目的:

        String certPath = System.getProperty("my.cert.path");
String certPassword = System.getProperty("my.cert.password");

in = new FileInputStream(new File(certPath));
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(in, certPassword.toCharArray());
in.close();

KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, certPassword.toCharArray());
KeyManager[] keymanagers = kmf.getKeyManagers();

SSLContext context = SSLContext.getInstance("TLS");
context.init(keymanagers, null, null);
SSLSocketFactory sslSocketFactory = context.getSocketFactory();

HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
// do HTTP connection OPS :)

关于java - 禁用 JDBC 连接上的 keystore ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16898126/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com