Qualcuno ha qualche suggerimento amichevole su come eseguire l'autenticazione del client tramite un certificato x509 utilizzando HTTPClient 4.0.1?Autenticazione reciproca con certificati x509 utilizzando HttpClient 4.0.1
Grazie per il vostro tempo.
Qualcuno ha qualche suggerimento amichevole su come eseguire l'autenticazione del client tramite un certificato x509 utilizzando HTTPClient 4.0.1?Autenticazione reciproca con certificati x509 utilizzando HttpClient 4.0.1
Grazie per il vostro tempo.
Ecco un codice per iniziare. KeyStore
è l'oggetto che contiene il certificato client. Se il server utilizza un certificato autofirmato o un certificato non firmato da una CA come riconosciuto dalla JVM nel file cacerts incluso, sarà necessario utilizzare uno TrustStore
. In caso contrario, utilizzare il file cacerts predefinite, passare null
per SSLSockeFactory
per l'argomento 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);
Un'altra soluzione (copiato da un altro esempio). Ho usato lo stesso keystore sia per 'trusting' (trustStore) sia per autenticarmi (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();
}
Ho utilizzato quanto segue da un codice di esempio sul sito Web di HttpClient (contesto SSL personalizzato se non ricordo male).
{
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();
}
}
Un collegamento alla sorgente sarebbe utile ... –
@EvilRaat http://hc.apache.org/httpcomponents-client-4.3.x/httpclient/examples/org/apache/http/examples/client/ClientCustomSSL.java da http: // hc .apache.org/httpcomponents-client-4.3.x/examples.html – EpicPandaForce
Grazie. Lo controllerò presto. – hooknc
Questa soluzione ha funzionato perfettamente. Grazie per il vostro aiuto. FYI, a causa di problemi di rinegoziazione SSL Handshake ho dovuto impostare la seguente proprietà della macchina virtuale: -Dsun.security.ssl.allowUnsafeRenegotiation = true Sono/stava lavorando con Java 1.6.0_20 e Tomcat 6.0.29. – hooknc
Il commento sopra non è più necessario quando si lavora con jdk 1.6.0_24 o successivo. – hooknc