public HttpClientVM() {
BasicHttpParams params = new BasicHttpParams();
ConnManagerParams.setMaxTotalConnections(params, 10);
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setUseExpectContinue(params, false);
HttpConnectionParams.setStaleCheckingEnabled(params, true);
HttpConnectionParams.setConnectionTimeout(params, 30000);
HostnameVerifier hostnameVerifier=
org.Apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http",socketFactory, 80));
schemeRegistry.register(new Scheme("https",socketFactory, 443));
ThreadSafeClientConnManager manager = new ThreadSafeClientConnManager(params, schemeRegistry);
// Set verifier
client = new DefaultHttpClient(manager, params);
}
Problème:
Lors de l'exécution de client.accessURL(url)
, l'erreur suivante se produit:
Exception in thread "main" javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
at com.Sun.net.ssl.internal.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.Java:352)
at org.Apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.Java:128)
at org.Apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.Java:397)
at org.Apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.Java:495)
at org.Apache.http.conn.scheme.SchemeSocketFactoryAdaptor.connectSocket(SchemeSocketFactoryAdaptor.Java:62)
at org.Apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.Java:148)
at org.Apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.Java:150)
at org.Apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.Java:121)
at org.Apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.Java:575)
at org.Apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.Java:425)
at org.Apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.Java:820)
at org.Apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.Java:754)
at org.Apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.Java:732)
Information additionnelle:
Le certificat expiré était la cause de notre "exception javax.net.ssl.SSLPeerUnverifiedExverified: peer not authentified".
keytool -list -v -keystore filetruststore.ts
Enter keystore password:
Keystore type: JKS
Keystore provider: Sun
Your keystore contains 1 entry
Alias name: somealias
Creation date: Jul 26, 2012
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Unknown, OU=SomeOU, O="Some Company, Inc.", L=SomeCity, ST=GA, C=US
Issuer: CN=Unknown, OU=SomeOU, O=Some Company, Inc.", L=SomeCity, ST=GA, C=US
Serial number: 5011a47b
Valid from: Thu Jul 26 16:11:39 EDT 2012 until: Wed Oct 24 16:11:39 EDT 2012
Cette erreur est due au fait que votre serveur ne possède pas de certificat SSL valide. Par conséquent, nous devons dire au client d’utiliser un autre gestionnaire TrustManager. Voici un exemple de code:
SSLContext ctx = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
ctx.init(null, new TrustManager[]{tm}, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
ClientConnectionManager ccm = base.getConnectionManager();
SchemeRegistry sr = ccm.getSchemeRegistry();
sr.register(new Scheme("https", 443, ssf));
client = new DefaultHttpClient(ccm, base.getParams());
Cette exception survient dans le cas où votre serveur est basé sur JDK 7 et que votre client est sur JDK 6 et utilise des certificats SSL. Le protocole de transfert de message sslv2hello dans JDK 7 est désactivé par défaut, tandis que le protocole de transfert de message sslv2hello dans JDK 6 est activé. Pour cette raison, lorsque votre client tente de se connecter au serveur, un message sslv2hello sera envoyé au serveur et, en raison du message sslv2hello désactivé, vous obtiendrez cette exception. Pour résoudre ce problème, vous devez déplacer votre client vers JDK 7 ou utiliser la version 6u91 de JDK. Mais pour obtenir cette version de JDK, vous devez obtenir le support d'entreprise MOS (My Oracle Support) Enterprise. Ce patch n'est pas public.
Vous pouvez l'obtenir si le client spécifie "https" mais que le serveur exécute uniquement "http". Le serveur ne s'attend donc pas à établir une connexion sécurisée.
Cela peut également se produire si vous essayez de vous connecter via HTTPS et que le serveur n'est pas configuré pour gérer correctement les connexions SSL.
Je voudrais vérifier les paramètres SSL de vos serveurs d'applications et m'assurer que la certification est configurée correctement.
Dans mon cas, j'utilisais un client JDK 8 et le serveur utilisait d'anciens chiffrements non sécurisés. Le serveur est Apache et j'ai ajouté cette ligne à la configuration Apache:
SSLCipherSuite ALL:!ADH:RC4+RSA:+HIGH:!MEDIUM:!LOW:!SSLv2:!EXPORT
Vous devriez utiliser un outil comme celui-ci pour vérifier que votre configuration SSL est actuellement sécurisée: https://www.ssllabs.com/ssltest/analyze.html