Does anyone have any friendly tips on how t开发者_高级运维o perform client authentication via an x509 certificate using HTTPClient 4.0.1?
Here is some code to get you going. The KeyStore
is the object that contains the client certificate. If the server is using a self-signed certificate or a certificate that isn't signed by a CA as recognized by the JVM in the included cacerts file then you will need to use a TrustStore
. Otherwise to use the default cacerts file, pass in null
to SSLSockeFactory
for the truststore argument..
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);
Another solution (copied from another example). I've used the same keystore for both 'trusting' (trustStore) and for authenticate myself (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();
}
I used the following from a sample code on HttpClient's website (custom SSL context if I remember correctly).
{
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();
}
}
精彩评论