我有一些应用程序需要在同一个应用程序服务器中运行.每个应用程序都需要使用特定于该应用程序的证书通过同一Web服务进行身份验证.
显然,我可以将所有证书放在同一个密钥库中,但是如何指定我必须使用哪个?
对于我正在使用Spring webservicetemplate的调用,我想找到一些可以在spring xml配置文件中轻松配置的东西.
我试图遵循这个:
How can I have multiple SSL certificates for a Java server
整个概念很清楚但我无法理解如何将它与Spring webservicetemplate链接以及如何在调用内部指定我必须使用的证书.
最佳答案
我找到了解决方案.它不完美,或完全干净.
我需要更多的测试,以确保它正在运行,在它运行的那一刻.
我需要更多的测试,以确保它正在运行,在它运行的那一刻.
这是神奇的factorybean“CustomSSLHttpClientFactory.java”.
package foo.bar.services;
import java.io.InputStream;
import java.net@R_502_6407@cket;
import java.security.KeyStore;
import java.util.Map;
import javax.net.ssl.SSLContext;
import org.apache.http.client.HttpClient;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.conn@R_502[email protected];
import org.apache.http.conn@R_502[email protected];
import org.apache.http.conn.ssl.PrivateKeyDetails;
import org.apache.http.conn.ssl.PrivateKeyStrategy;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
import org.springframework.beans.factory.factorybean;
import org.springframework.core.io.Resource;
/**
* Custom SSL HttpClientFactoy.
* It allow to specify the certificate for a single specific implementation.
* It's needed when you have a single URL to call but different certificate,each one specific for a single page/function/user
*
* @author roberto.gabrieli
*
*/
public class CustomSSLHttpClientFactory implements factorybeanaram keyStoreFile org.springframework.core.io.Resource to specify the keystore
* @param keyStorePassword
* @param keyStoreType if null default JKS will be used
* @param trustStoreFile
* @param trustStorePassword
* @param allowedProtocols authentication protocols
* @param certAlias the client certificate alias. If null default behavior
*/
public CustomSSLHttpClientFactory(Resource keyStoreFile,String keyStorePassword,String keyStoreType,Resource trustStoreFile,String trustStorePassword,String[] allowedProtocols,String certAlias)
{
super();
this.keyStoreFile = keyStoreFile;
this.keyStorePassword = keyStorePassword;
this.keyStoreType = keyStoreType;
this.trustStoreFile = trustStoreFile;
this.trustStorePassword = trustStorePassword;
this.allowedProtocols = allowedProtocols;
this.certAlias = certAlias;
}
/**
* Little trick to pass over some stupid contentLength error
*
* @author roberto.gabrieli
*/
private class ContentLengthHeaderRemover implements HttpRequestInterceptor
{
@Override
public void process(HttpRequest request,HttpContext context) throws HttpException,IOException
{
request.removeHeaders(HTTP.CONTENT_LEN);// fighting org.apache.http.protocol.RequestContent's ProtocolException("Content-Length header already present");
}
}
/**
* Private class to hack the certificate alias choice.
*
* @author roberto.gabrieli
*
*/
private class AliasPrivateKeyStrategy implements PrivateKeyStrategy
{
private String alias;
public AliasPrivateKeyStrategy(String alias)
{
this.alias = alias;
}
/**
* This metod return the alias name specified in the constructor.
*/
public String chooseAlias(Mapetobject() throws Exception
{
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
KeyStore keyStore = KeyStore.getInstance(this.keyStoreType != null ? this.keyStoreType : KeyStore.getDefaultType());
InputStream instreamTrust = trustStoreFile.getInputStream();
InputStream instreamKeys = keyStoreFile.getInputStream();
//Load of KEYSTORE and TRUSTSTORE
try
{
trustStore.load(instreamTrust,trustStorePassword.tochararray());
keyStore.load(instreamKeys,keyStorePassword.tochararray());
}
finally
{
instreamKeys.close();
instreamTrust.close();
}
SSLContextBuilder sslCtxBuilder = SSLContexts.custom().loadTrustMaterial(trustStore,new TrustSelfSignedStrategy());
PrivateKeyStrategy apks = null;
// check if the alias is specified null and "" will mean -no alias-
if ( this.certAlias != null && !this.certAlias.trim().equals("") )
{
apks = new AliasPrivateKeyStrategy(this.certAlias);
sslCtxBuilder = sslCtxBuilder.loadKeyMaterial(keyStore,keyStorePassword.tochararray(),apks);
}
else
{
sslCtxBuilder = sslCtxBuilder.loadKeyMaterial(keyStore,keyStorePassword.tochararray());
}
SSLContext sslcontext = sslCtxBuilder.build();
//All the stuff for the connection build
HttpClientBuilder builder = HttpClientBuilder.create();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,allowedProtocols,null,SSLConnectionSocketFactory.broWSER_COMPATIBLE_HOSTNAME_VERIFIER);
builder.setSSLSocketFactory(sslsf);
RegistryetobjectType()
{
return HttpClient.class;
}
public boolean isSingleton()
{
return false;
}
}
这是“spring-config.xml”中所需的配置
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。