我一直在尝试使用Camel实现2-way SSL/HTTPS代理。我已经成功设置了Jetty组件,使用2-way SSL,并且现在正在尝试通过Http4组件来完成代理的客户端部分。
当我将Jetty流量路由到日志组件时,一切正常,2 way SSL信任链也没有问题。但是,当我加入Http4组件时,它会出现对等体未经过身份验证的异常。我正在使用Camel 2.7.0版本。
以下是我目前的进展。
据我所知,在代理连接的两端使用的所有密钥库/信任库之间应该是没有问题的信任关系。
以下是我的堆栈跟踪。
[ qtp25584663-14] HttpProducer DEBUG 执行http POST方法: https4://soafa-lite-staging:443/axis2/services/SigActService?bridgeEndpoint=true&throwExceptionOnFailure=false [ qtp25584663-14] DefaultErrorHandler DEBUG 交付失败,exchangeId: ID-ubuntu-46528-1303140195358-0-1。第一次尝试交付时捕获到: javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated [ qtp25584663-14] DefaultErrorHandler ERROR 交付失败,exchangeId: ID-ubuntu-46528-1303140195358-0-1。尝试交付1次后耗尽,捕获到: javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated at com.sun.net.ssl.internal.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:352) at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:128) at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:390) at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:148) at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:149) at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:121) at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:561) at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:415) at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820) at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754) at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:732) at org.apache.camel.component.http4.HttpProducer.executeMethod(HttpProducer.java:187) at org.apache.camel.component.http4.HttpProducer.process(HttpProducer.java:101) at org.apache.camel.impl.converter.AsyncProcessorTypeConverter$ProcessorToAsyncProcessorBridge.process(AsyncProcessorTypeConverter.java:50) at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:77) at org.apache.camel.processor.SendProcessor$2.doInAsyncProducer(SendProcessor.java:104) at org.apache.camel.impl.ProducerCache.doInAsyncProducer(ProducerCache.java:272) at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:98) at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:77) at org.apache.camel.processor.DelegateAsyncProcessor.processNext(DelegateAsyncProcessor.java:98) at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:89) at org.apache.camel.processor.interceptor.TraceInterceptor.process(TraceInterceptor.java:99) at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:77) at org.apache.camel.processor.RedeliveryErrorHandler.processErrorHandler(RedeliveryErrorHandler.java:299) at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:208) at org.apache.camel.processor.DefaultChannel.process(DefaultChannel.java:269) at org.apache.camel.processor.UnitOfWorkProcessor.process(UnitOfWorkProcessor.java:109) at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:77) at org.apache.camel.processor.DelegateAsyncProcessor.processNext(DelegateAsyncProcessor.java:98) at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:89) at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:68) at org.apache.camel.component.jetty.CamelContinuationServlet.service(CamelContinuationServlet.java:109) at javax.servlet.http.HttpServlet.service(HttpServlet.java:820) at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:534) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1351) at org.eclipse.jetty.servlets.MultiPartFilter.doFilter(MultiPartFilter.java:97) at org.apache.camel.component.jetty.CamelMultipartFilter.doFilter(CamelMultipartFilter.java:41) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1322) at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:473) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:929) at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:403) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:864)
当我将Jetty流量路由到日志组件时,一切正常,2 way SSL信任链也没有问题。但是,当我加入Http4组件时,它会出现对等体未经过身份验证的异常。我正在使用Camel 2.7.0版本。
以下是我目前的进展。
public static void main(String[] args) throws Exception {
CamelContext context = new DefaultCamelContext();
JettyHttpComponent jetty = context.getComponent("jetty", JettyHttpComponent.class);
SslSelectChannelConnector sslConnector = new SslSelectChannelConnector();
sslConnector.setPort(9443);
sslConnector.setKeystore("/home/brian/jboss.keystore");
sslConnector.setKeyPassword("changeit");
sslConnector.setTruststore("/home/brian/jboss.truststore");
sslConnector.setTrustPassword("changeit");
sslConnector.setPassword("changeit");
sslConnector.setNeedClientAuth(true);
Map<Integer, SslSelectChannelConnector> connectors = new HashMap<Integer, SslSelectChannelConnector>();
connectors.put(9443, sslConnector);
jetty.setSslSocketConnectors(connectors);
final Endpoint jettyEndpoint = jetty.createEndpoint("jetty:https://localhost:9443/service");
KeyStore keystore = KeyStore.getInstance("PKCS12");
keystore.load(new FileInputStream(new File("/home/brian/User2.p12")), "Password1234!".toCharArray());
X509KeyManager keyManager = new CTSKeyManager(keystore, "user2", "Password1234!".toCharArray());
KeyManager[] keyManagers = new KeyManager[] { keyManager };
X509TrustManager trustManager = new EasyTrustManager();
TrustManager[] trustManagers = new TrustManager[] { trustManager };
SSLContext sslcontext = SSLContext.getInstance("TLS");
sslcontext.init(keyManagers, trustManagers, null);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("https", 443, new SSLSocketFactory(sslcontext,
SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)));
HttpComponent http4 = context.getComponent("http4", HttpComponent.class);
http4.setClientConnectionManager(new ThreadSafeClientConnManager(registry));
final Endpoint https4Endpoint = http4
.createEndpoint("https4://soafa-lite-staging:443/axis2/services/SigActService?bridgeEndpoint=true&throwExceptionOnFailure=false");
context.addRoutes(new RouteBuilder() {
@Override
public void configure() {
from(jettyEndpoint).to(https4Endpoint);
}
});
context.start();
context.stop();
}
private static class EasyTrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
private static class CTSKeyManager extends X509ExtendedKeyManager {
private final KeyStore keystore;
private final char[] privateKeyPassword;
private final String privateKeyAlias;
public CTSKeyManager(KeyStore keystore, String privateKeyAlias, char[] privateKeyPassword) {
this.keystore = keystore;
this.privateKeyAlias = privateKeyAlias;
this.privateKeyPassword = privateKeyPassword;
}
@Override
public String[] getServerAliases(String keyType, Principal[] issuers) {
String[] serverAliases = null;
try {
List<String> aliasList = new ArrayList<String>();
int count = 0;
Enumeration<String> aliases = keystore.aliases();
while (aliases.hasMoreElements()) {
String alias = aliases.nextElement();
aliasList.add(alias);
count++;
}
serverAliases = aliasList.toArray(new String[count]);
} catch (Exception e) {
}
return serverAliases;
}
@Override
public PrivateKey getPrivateKey(String alias) {
PrivateKey privateKey = null;
try {
privateKey = (PrivateKey) keystore.getKey(alias, privateKeyPassword);
} catch (Exception e) {
}
return privateKey;
}
@Override
public String[] getClientAliases(String keyType, Principal[] issuers) {
return privateKeyAlias == null ? null : new String[] { privateKeyAlias };
}
@Override
public X509Certificate[] getCertificateChain(String alias) {
X509Certificate[] x509 = null;
try {
Certificate[] certs = keystore.getCertificateChain(alias);
if (certs == null || certs.length == 0) {
return null;
}
x509 = new X509Certificate[certs.length];
for (int i = 0; i < certs.length; i++) {
x509[i] = (X509Certificate) certs[i];
}
} catch (Exception e) {
}
return x509;
}
@Override
public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
return privateKeyAlias;
}
@Override
public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
return privateKeyAlias;
}
@Override
public String chooseEngineClientAlias(String[] keyType, Principal[] issuers, SSLEngine engine) {
return privateKeyAlias;
}
@Override
public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine) {
return privateKeyAlias;
}
}
}
据我所知,在代理连接的两端使用的所有密钥库/信任库之间应该是没有问题的信任关系。
以下是我的堆栈跟踪。
[ qtp25584663-14] HttpProducer DEBUG 执行http POST方法: https4://soafa-lite-staging:443/axis2/services/SigActService?bridgeEndpoint=true&throwExceptionOnFailure=false [ qtp25584663-14] DefaultErrorHandler DEBUG 交付失败,exchangeId: ID-ubuntu-46528-1303140195358-0-1。第一次尝试交付时捕获到: javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated [ qtp25584663-14] DefaultErrorHandler ERROR 交付失败,exchangeId: ID-ubuntu-46528-1303140195358-0-1。尝试交付1次后耗尽,捕获到: javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated at com.sun.net.ssl.internal.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:352) at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:128) at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:390) at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:148) at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:149) at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:121) at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:561) at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:415) at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820) at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754) at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:732) at org.apache.camel.component.http4.HttpProducer.executeMethod(HttpProducer.java:187) at org.apache.camel.component.http4.HttpProducer.process(HttpProducer.java:101) at org.apache.camel.impl.converter.AsyncProcessorTypeConverter$ProcessorToAsyncProcessorBridge.process(AsyncProcessorTypeConverter.java:50) at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:77) at org.apache.camel.processor.SendProcessor$2.doInAsyncProducer(SendProcessor.java:104) at org.apache.camel.impl.ProducerCache.doInAsyncProducer(ProducerCache.java:272) at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:98) at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:77) at org.apache.camel.processor.DelegateAsyncProcessor.processNext(DelegateAsyncProcessor.java:98) at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:89) at org.apache.camel.processor.interceptor.TraceInterceptor.process(TraceInterceptor.java:99) at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:77) at org.apache.camel.processor.RedeliveryErrorHandler.processErrorHandler(RedeliveryErrorHandler.java:299) at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:208) at org.apache.camel.processor.DefaultChannel.process(DefaultChannel.java:269) at org.apache.camel.processor.UnitOfWorkProcessor.process(UnitOfWorkProcessor.java:109) at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:77) at org.apache.camel.processor.DelegateAsyncProcessor.processNext(DelegateAsyncProcessor.java:98) at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:89) at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:68) at org.apache.camel.component.jetty.CamelContinuationServlet.service(CamelContinuationServlet.java:109) at javax.servlet.http.HttpServlet.service(HttpServlet.java:820) at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:534) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1351) at org.eclipse.jetty.servlets.MultiPartFilter.doFilter(MultiPartFilter.java:97) at org.apache.camel.component.jetty.CamelMultipartFilter.doFilter(CamelMultipartFilter.java:41) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1322) at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:473) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:929) at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:403) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:864)