使用HttpClient 4.0.1与x509证书进行相互身份validation

有没有人有关于如何使用HTTPClient 4.0.1通过x509证书执行客户端身份validation的任何友好提示?

感谢您的时间。

这里有一些代码可以帮助你。 KeyStore是包含客户端证书的对象。 如果服务器正在使用自签名证书或未由CA签名的证书(由JVM在包含的cacerts文件中识别),则您将需要使用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); 

另一个解决方案(从另一个例子复制)。 我已经使用相同的密钥库来“信任”(trustStore)和自我validation(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(); } 

我在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(); } }