我已经尝试用谷歌搜索这个问题了几天,但我仍然卡住了,所以我会尝试在这里寻求一些帮助。
这是情况。我正在开发的 EJB 必须连接到安全的 Web 服务。连接需要相互认证,所以我有一个公共ID链和一个个人证书。我从文件中加载这些信息,并构建我自己的 SSLSocketFactory(Apache HttpClient 之一)
// Queste proprietà servono perché senza di loro WebSphere 6.1 non
// capisce un cazzo
Security.setProperty("security.provider.1", "com.ibm.jsse2.IBMJSSEProvider2");
Security.setProperty("security.provider.2", "com.ibm.crypto.fips.provider.IBMJCEFIPS");
Security.setProperty("security.provider.3", "com.ibm.crypto.provider.IBMJCE");
Security.setProperty("security.provider.4", "com.ibm.security.jgss.IBMJGSSProvider");
Security.setProperty("security.provider.5", "com.ibm.security.cert.IBMCertPath");
Security.setProperty("security.provider.6", "com.ibm.security.sasl.IBMSASL");
Security.setProperty("ssl.SocketFactory.provider", "com.ibm.jsse2.SSLSocketFactoryImpl");
Security.setProperty("ssl.ServerSocketFactory.provider", "com.ibm.jsse2.SSLServerSocketFactoryImpl");
// d) SETUP KS, TS e SSL
InitialContext ctx = new InitialContext();
// keystore
KeyManager[] keyManagers;
TrustManager[] trustManagers;
try {
URI keyStoreUri = ((URL) ctx.lookup(JNDI_INPS_KEY_STORE_PATH))
.toURI();
String keyStorePassword = "test2012";
KeyStore keyStore = loadKeyStoreFromFile(keyStoreUri,
keyStorePassword);
KeyManagerFactory keyManagerFactory = KeyManagerFactory
.getInstance("IBMX509");
keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());
keyManagers = keyManagerFactory.getKeyManagers();
URI trustStoreUri = ((URL) ctx.lookup(JNDI_INPS_TRUST_STORE_PATH))
.toURI();
String trustStorePassword = "inpsChain";
KeyStore trustStore = loadKeyStoreFromFile(trustStoreUri,
trustStorePassword);
TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance("IBMX509");
trustManagerFactory.init(trustStore);
trustManagers = trustManagerFactory.getTrustManagers();
} catch (NameNotFoundException ex) {
throw new ErroreApplicativo("USINPS001", ErroreApplicativo.ERRORE,
"", null);
}
SSLContext sslCtx = SSLContext.getInstance("TLS");
sslCtx.init(keyManagers,
new TrustManager[] { new TrustfulTrustManager() }, null);
SSLSocketFactory sslSocketFactory = new SSLSocketFactory(sslCtx);
Scheme httpsScheme = new Scheme("https", HTTPS_PORT, sslSocketFactory);
Scheme httpScheme = new Scheme("http", HTTP_PORT, sslSocketFactory); // Which socket factory should I use?
final SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(httpScheme);
schemeRegistry.register(httpsScheme);
PoolingClientConnectionManager connManager = new PoolingClientConnectionManager(
schemeRegistry);
密码是临时写在代码中的,但是一旦解决方案起作用,它们就会被参数化。
我必须使用代理来拨打电话。我从来没有做过这种事情,但我想我必须使用 http 隧道,因为证书在我的服务器中,而不是在代理中。所以我设置了一个 HttpRoute (仍然是一个 HttpClient 类)......
System.setProperty("java.net.useSystemProxies", "false");
Resources res = new Resources();
String proxyHost = res.get(PROXY_HOST);
int proxyPort = Integer.parseInt(res.get(PROXY_PORT));
final HttpHost proxy = new HttpHost(proxyHost, proxyPort, "http");
String inpsProtocol = inpsHostURI.getScheme();
String inpsHostName = inpsHostURI.getHost();
final HttpHost inpsHost = new HttpHost(inpsHostName, HTTPS_PORT,
inpsProtocol);
HttpRoutePlanner planner = new HttpRoutePlanner() {
public HttpRoute determineRoute(HttpHost arg0, HttpRequest arg1,
HttpContext arg2) throws HttpException {
// TODO Stub di metodo generato automaticamente
try {
return new HttpRoute(inpsHost, Inet4Address.getLocalHost(),
proxy, true, TunnelType.TUNNELLED,
LayerType.LAYERED);
} catch (UnknownHostException e) {
return null;
}
}
};
...并发送消息...
DefaultHttpClient httpClient = new DefaultHttpClient(connManager);
httpClient.setRoutePlanner(planner);
HttpResponse resp = httpClient.execute(httpPost);
答案总是一样的:HTTP500,我不确定是来自代理还是我正在调用的 SSL 服务器。
一些问题:
我应该为 HTTP 方案使用哪个套接字工厂?我应该使用与其他套接字相同的 SSL 工厂还是 HTTPClient 附带的普通套接字工厂?
什么是 LayerType.LAYERED 参数,它是什么意思?