我有这个简单的JMX客户端
public void testTomcatBasicAuthentication() throws Exception
{
System.out.println("Test Server Basic Authentication");
try
{
String truststore = "C:\\client.jks";
String trustStorePassword = "password";
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://xxx.xxx.xxx.xxx:9999/jmxrmi");
HashMap environment = new HashMap();
String[] credentials = new String[]
{
"user", "passwd"
};
environment.put(JMXConnector.CREDENTIALS, credentials);
// environment.put("javax.net.ssl.trustStore", truststore);
// environment.put("javax.net.ssl.trustStorePassword", trustStorePassword);
// environment.put("javax.net.ssl.keyStore", truststore);
// environment.put("javax.net.ssl.keyStorePassword", trustStorePassword);
KeyManager[] kms = getKeyManagers(truststore, trustStorePassword);
TrustManager[] tms = getTrustManagers(truststore, trustStorePassword);
System.setProperty("javax.net.ssl.trustStore", truststore);
System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword);
System.setProperty("javax.net.ssl.keyStore", truststore);
System.setProperty("javax.net.ssl.keyStorePassword", trustStorePassword);
JMXConnector jmxc = JMXConnectorFactory.connect(url, environment);
MBeanServerConnection server = jmxc.getMBeanServerConnection();
Set<ObjectName> s2 = server.queryNames(new ObjectName("Catalina:type=Server,*"), null);
for (ObjectName obj : s2)
{
ObjectName objname = new ObjectName(obj.getCanonicalName());
System.out.println("serverInfo " + server.getAttribute(objname, "serverInfo"));
System.out.println("address " + server.getAttribute(objname, "address"));
System.out.println("stateName " + server.getAttribute(objname, "stateName"));
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
如何用Java代码替换System.setProperty(....)
?我不想使用System.setProperty
。
编辑。我找到了这个example
我们可以使用此代码吗?
KeyManager[] kms = getKeyManagers(truststore, trustStorePassword);
TrustManager[] tms = getTrustManagers(truststore, trustStorePassword);
SslContext.setCurrentSslContext(new SslContext(kms, tms, null));
private static TrustManager[] getTrustManagers(String location, String password)
throws IOException, GeneralSecurityException
{
// First, get the default TrustManagerFactory.
String alg = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmFact = TrustManagerFactory.getInstance(alg);
FileInputStream fis = new FileInputStream(location);
KeyStore ks = KeyStore.getInstance("jks");
ks.load(fis, password.toCharArray());
fis.close();
tmFact.init(ks);
// And now get the TrustManagers
TrustManager[] tms = tmFact.getTrustManagers();
return tms;
}
private static KeyManager[] getKeyManagers(String location, String password)
throws IOException, GeneralSecurityException
{
// First, get the default KeyManagerFactory.
String alg = KeyManagerFactory.getDefaultAlgorithm();
KeyManagerFactory kmFact = KeyManagerFactory.getInstance(alg);
FileInputStream fis = new FileInputStream(location);
KeyStore ks = KeyStore.getInstance("jks");
ks.load(fis, password.toCharArray());
fis.close();
// Now we initialise the KeyManagerFactory with this KeyStore
kmFact.init(ks, password.toCharArray());
// And now get the KeyManagers
KeyManager[] kms = kmFact.getKeyManagers();
return kms;
}
private static KeyStore keyStoreFromCertificateString(String alias, String certificateString)
throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException
{
KeyStore ks = KeyStore.getInstance("jks");
ks.load(null); // Create empty key store
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate cert = cf.generateCertificate(new ByteArrayInputStream(certificateString.getBytes()));
ks.setEntry(alias, new KeyStore.TrustedCertificateEntry(cert), null);
return ks;
}
您能否了解我们如何整合此代码,或者应该有其他解决方案?
答案 0 :(得分:6)
看起来它应该相对简单,但事实并非如此。
您需要在环境中传递实际套接字工厂类,请参阅this example。但是,该示例中使用的实现使用jvm默认套接字工厂。相反,您需要使用适当的密钥库和信任库来设置自己的SSL*SocketFactory
实例。然后,您需要使用配置的套接字工厂实现自己的RMI*SocketFactory
实例。您可以将jdk impls用作指南,SslRMIClientSocketFactory和SslRMIServerSocketFactory。
答案 1 :(得分:2)
我担心你的问题不是很好。我写道你要替换System.setProperty
,但对我而言,实际你想要使用自定义信任/密钥存储。
已经回答:Using a custom truststore in java as well as the default one
您找到的示例只是解决方案的一半。创建连接时必须使用相应的管理器。像这样:
sslContext.init(null, trustManagers, null);
connection.setSSLSocketFactory(sslContext.getSocketFactory());
来源:https://planet.jboss.org/post/creating_https_connection_without_javax_net_ssl_truststore_property
但如果您不控制实际的连接创建,则可能必须使用全局属性。 (或者您的应用程序服务器具有的任何配置机制)
答案 2 :(得分:0)
使这项工作的一个简单易用的解决方法是使用单独的每个线程的系统属性副本,正如here中所解释的那样(有趣的是,自我关注的主要问题是与你的问题相同)。之后,在系统属性上设置 keyStore 和 trustStore 将是线程本地的。
确保为两个不同的ssl连接使用不同的线程。