如何使用 setProperty 设置不同的信任库密钥库
How to set different truststore keystore with setProperty
我有一个固定客户端,它使用不同的密钥库(公司一个密钥库)调用固定服务器。在我的 java 中,每次我这样设置 trustStore 和 keyStore 系统属性时:
..reading path and password from database..
System.setProperty("javax.net.ssl.trustStore", ..path..);
System.setProperty("javax.net.ssl.trustStorePassword", ..password..);
System.setProperty("javax.net.ssl.keyStore", ..path..);
System.setProperty("javax.net.ssl.keyStorePassword", ..password);
这样,它只在我第一次调用服务器时起作用(示例"Company A")。当我尝试使用另一个密钥库(例如 "Company B")调用服务器时,服务器的响应是:
javax.xml.ws.soap.SOAPFaultException: IDP Rule 'Process Error' aborted processing.
这是因为System.setProperty不是每次都刷新,所以第一次之后客户端总是有"Company A"的keystore。
我也试过将所有经过认证的都放在一个密钥库中,但它不起作用。在这种情况下,我认为所有密码都必须相同。
一些想法?
Misantrops 回复后更新
我试过这个代码:
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream trustStore1 = new FileInputStream(path1);
keyStore.load(trustStore1, password1.toCharArray());
trustStore1.close();
InputStream trustStore2 = new FileInputStream(path2);
keyStore.load(trustStore2, password2.toCharArray());
trustStore2.close();
InputStream trustStore3 = new FileInputStream(path3);
keyStore.load(trustStore3, password3.toCharArray());
trustStore3.close();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, tmf.getTrustManagers(), null);
SSLSocketFactory sslFactory = ctx.getSocketFactory();
它return这个错误:
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target.] with root cause
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
终于找到了解决办法:
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
String path1 = ..absolute path of keystore..
path1 = path1.replaceAll("%20", " ");
InputStream trustStore1 = new FileInputStream(path1);
keyStore.load(trustStore1, new String(..keystore password..).toCharArray());
trustStore1.close();
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(keyStore, new String(..keystore password..).toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
SSLContext ctx = SSLContext.getInstance("SSL");
ctx.init(keyManagerFactory.getKeyManagers(), tmf.getTrustManagers(), null);
HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory());
可以在运行时更改密钥库,只需使用对象 SSLContext 的方法 "init"。这个函数的参数是 KeyManager 和 TrustManager,像在脚本中一样初始化。因此,通过这种方式可以模拟 System.setProperty。
谢谢大家!
我有一个固定客户端,它使用不同的密钥库(公司一个密钥库)调用固定服务器。在我的 java 中,每次我这样设置 trustStore 和 keyStore 系统属性时:
..reading path and password from database..
System.setProperty("javax.net.ssl.trustStore", ..path..);
System.setProperty("javax.net.ssl.trustStorePassword", ..password..);
System.setProperty("javax.net.ssl.keyStore", ..path..);
System.setProperty("javax.net.ssl.keyStorePassword", ..password);
这样,它只在我第一次调用服务器时起作用(示例"Company A")。当我尝试使用另一个密钥库(例如 "Company B")调用服务器时,服务器的响应是:
javax.xml.ws.soap.SOAPFaultException: IDP Rule 'Process Error' aborted processing.
这是因为System.setProperty不是每次都刷新,所以第一次之后客户端总是有"Company A"的keystore。 我也试过将所有经过认证的都放在一个密钥库中,但它不起作用。在这种情况下,我认为所有密码都必须相同。 一些想法?
Misantrops 回复后更新
我试过这个代码:
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream trustStore1 = new FileInputStream(path1);
keyStore.load(trustStore1, password1.toCharArray());
trustStore1.close();
InputStream trustStore2 = new FileInputStream(path2);
keyStore.load(trustStore2, password2.toCharArray());
trustStore2.close();
InputStream trustStore3 = new FileInputStream(path3);
keyStore.load(trustStore3, password3.toCharArray());
trustStore3.close();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, tmf.getTrustManagers(), null);
SSLSocketFactory sslFactory = ctx.getSocketFactory();
它return这个错误:
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target.] with root cause
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
终于找到了解决办法:
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
String path1 = ..absolute path of keystore..
path1 = path1.replaceAll("%20", " ");
InputStream trustStore1 = new FileInputStream(path1);
keyStore.load(trustStore1, new String(..keystore password..).toCharArray());
trustStore1.close();
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(keyStore, new String(..keystore password..).toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
SSLContext ctx = SSLContext.getInstance("SSL");
ctx.init(keyManagerFactory.getKeyManagers(), tmf.getTrustManagers(), null);
HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory());
可以在运行时更改密钥库,只需使用对象 SSLContext 的方法 "init"。这个函数的参数是 KeyManager 和 TrustManager,像在脚本中一样初始化。因此,通过这种方式可以模拟 System.setProperty。 谢谢大家!