有没有人对如何使用HTTPClient 4.0.1通过x509证书执行客户端身份验证有任何友好提示?
感谢您的时间。
答案 0 :(得分:21)
这是一些让你前进的代码。 KeyStore
是包含客户端证书的对象。如果服务器正在使用自签名证书或未由CA签名的证书(包含在包含的cacerts文件中的JVM),则需要使用TrustStore
。否则,要使用默认的cacerts文件,请将null
传递给SSLSockeFactory
以获取truststore参数。
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
...
final HttpParams httpParams = new BasicHttpParams();
// load the keystore containing the client certificate - keystore type is probably jks or pkcs12
final KeyStore keystore = KeyStore.getInstance("pkcs12");
InputStream keystoreInput = null;
// TODO get the keystore as an InputStream from somewhere
keystore.load(keystoreInput, "keystorepassword".toCharArray());
// load the trustore, leave it null to rely on cacerts distributed with the JVM - truststore type is probably jks or pkcs12
KeyStore truststore = KeyStore.getInstance("pkcs12");
InputStream truststoreInput = null;
// TODO get the trustore as an InputStream from somewhere
truststore.load(truststoreInput, "truststorepassword".toCharArray());
final SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("https", new SSLSocketFactory(keystore, keystorePassword, truststore), 443));
final DefaultHttpClient httpClient = new DefaultHttpClient(new ThreadSafeClientConnManager(httpParams, schemeRegistry), httpParams);
答案 1 :(得分:2)
另一个解决方案(从另一个例子复制)。我已经使用相同的密钥库来“信任”(trustStore)和自我验证(keyStore)。
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream instream = new FileInputStream(new File("miller.keystore"));
try {
trustStore.load(instream, "pw".toCharArray());
} finally {
instream.close();
}
SSLContext sslcontext = SSLContexts.custom()
.loadTrustMaterial(trustStore) /* this key store must contain the certs needed & trusted to verify the servers cert */
.loadKeyMaterial(trustStore, "pw".toCharArray()) /* this keystore must contain the key/cert of the client */
.build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient = HttpClients.custom()
.setSSLSocketFactory(sslsf)
.build();
try {
HttpGet httpget = new HttpGet("https://localhost");
System.out.println("executing request" + httpget.getRequestLine());
CloseableHttpResponse response = httpclient.execute(httpget);
try {
HttpEntity entity = response.getEntity();
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
if (entity != null) {
System.out.println("Response content length: " + entity.getContentLength());
}
EntityUtils.consume(entity);
} finally {
response.close();
}
} finally {
httpclient.close();
}
答案 2 :(得分:0)
我在HttpClient网站上的示例代码中使用了以下内容(如果我没记错的话,可以使用自定义SSL上下文)。
{
KeyStore keyStore = KeyStore.getInstance("PKCS12"); //client certificate holder
FileInputStream instream = new FileInputStream(new File(
"client-p12-keystore.p12"));
try {
trustStore.load(instream, "password".toCharArray());
} finally {
instream.close();
}
// Trust own CA and all self-signed certs
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(keyStore, "password".toCharArray())
// .loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()) //if you have a trust store
.build();
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext, new String[] { "TLSv1" }, null,
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient = HttpClients
.custom()
.setHostnameVerifier(
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER) //todo
.setSSLSocketFactory(sslsf).build();
try {
HttpGet httpget = new HttpGet("https://localhost:8443/secure/index");
System.out.println("executing request" + httpget.getRequestLine());
CloseableHttpResponse response = httpclient.execute(httpget);
try {
HttpEntity entity = response.getEntity();
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
if (entity != null) {
System.out.println("Response content length: "
+ entity.getContentLength());
}
EntityUtils.consume(entity);
} finally {
response.close();
}
} finally {
httpclient.close();
}
}