我们的应用程序中的Feign客户端正在与自签名服务器进行通信。我们能够使用属性javax.net.ssl.trustStore
系统属性使Feign客户端使用自定义信任库。但由于我的应用程序还与标准CA认证站点通信,因此不应覆盖默认信任库。
如何在不使用javax.net.ssl.trustStore
系统属性的情况下使用自定义信任库?或者我怎么能让我的Feign客户端使用标准javax.net.ssl.trustStore
系统属性以外的属性中的信任库?
我最终手工制作了我自己的SSLSocketFactory
实例,我将其传递给我的Feign客户端,使用下面的代码,
/**
* Gets the {@link SSLSocketFactory} instance for the client communication
* using the given truststore file and password.
*
* Since the instance is used as client, this is instantiated with empty
* keystore and the truststore represented by the given truststore file.
*
*
* @param theTrustStoreFile
* The complete file path of the truststore.
* @return {@link SSLSocketFactory} instance that internally uses the given
* truststore.
* @throws Exception
* When there is an error in the creating the
* {@link SSLSocketFactory} instance.
*/
public static SSLSocketFactory getClientSSLSocketFactory(File theTrustStoreFile)
throws Exception
{
// This supports TLSv1.2
SSLContext sslContext = SSLContext.getInstance("TLS");
KeyStore kStore = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream file = getFileInputStream(theTrustStoreFile);
kStore.load(file, null);
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(kStore);
sslContext.init(new KeyManager[] {}, tmf.getTrustManagers(), null);
return sslContext.getSocketFactory();
}
/**
* Reads the file into {@link FileInputStream} instance.
*
* @param file
* The file to be read.
* @return {@link FileInputStream} that represents the file content/
* @throws Exception
* When there is any error in reading the file.
*/
private static FileInputStream getFileInputStream(final File file) throws Exception
{
return AccessController.doPrivileged(new PrivilegedExceptionAction<FileInputStream>()
{
@Override
public FileInputStream run() throws Exception
{
try
{
if (file.exists())
{
return new FileInputStream(file);
} else
{
return null;
}
} catch (FileNotFoundException e)
{
// couldn't find it, oh well.
return null;
}
}
});
}
当我实例化我的客户端时,我会这样做,
Feign.builder().client(getClientSSLSocketFactory(trustFile),null)...
这个gist contains示例代码及其用法。