HttpClient met SSL

1. Overzicht

Dit artikel laat zien hoe configureer de Apache HttpClient 4 met "Accept All" SSL-ondersteuning. Het doel is simpel: gebruik HTTPS-URL's die geen geldige certificaten hebben.

Als je dieper wilt graven en andere coole dingen wilt leren die je kunt doen met de HttpClient - ga dan naar de belangrijkste HttpClient-gids.

2. Het SSLPeerUnverifiedException

Zonder SSL te configureren met de HttpClient, zal de volgende test - waarbij een HTTPS-URL wordt gebruikt - mislukken:

openbare klasse RestClientLiveManualTest {@Test (verwacht = SSLPeerUnverifiedException.class) openbare leegte whenHttpsUrlIsConsumed_thenException () gooit ClientProtocolException, IOException {CloseableHttpClient httpClient = HttpClients.createDefault (); String urlOverHttps = "// localhost: 8082 / httpclient-simple"; HttpGet getMethod = nieuwe HttpGet (urlOverHttps); HttpResponse-antwoord = httpClient.execute (getMethod); assertThat (response.getStatusLine (). getStatusCode (), equalTo (200)); }}

De exacte fout is:

javax.net.ssl.SSLPeerUnverifiedException: peer niet geverifieerd op sun.security.ssl.SSLSessionImpl.getPeerCertificates (SSLSessionImpl.java:397) op org.apache.http.conn.ssl.AbstractVerifier.verify (AbstractVerifier.java:126). ..

De javax.net.ssl.SSLPeerUnverifiedException uitzondering treedt op wanneer er geen geldige vertrouwensketen voor de URL kan worden vastgesteld.

3. SSL configureren - Alles accepteren (HttpClient <4.3)

Laten we nu de HTTP-client configureren om alle certificaatketens te vertrouwen, ongeacht hun geldigheid:

@Test openbare laatste leegte gegevenAcceptingAllCertificates_whenHttpsUrlIsConsumed_thenOk () gooit GeneralSecurityException {HttpComponentsClientHttpRequestFactory requestFactory = nieuwe HttpComponentsClientHttpRequestFactory (); CloseableHttpClient httpClient = (CloseableHttpClient) requestFactory.getHttpClient (); Campsitetrategy acceptingTrustStrategy = (cert, authType) -> true; SSLSocketFactory sf = nieuwe SSLSocketFactory (accepteertTrustStrategy, ALLOW_ALL_HOSTNAME_VERIFIER); httpClient.getConnectionManager (). getSchemeRegistry (). register (nieuw schema ("https", 8443, sf)); ResponseEntity response = nieuwe RestTemplate (requestFactory). exchange (urlOverHttps, HttpMethod.GET, null, String.class); assertThat (response.getStatusCode (). value (), equalTo (200)); }

Met de nieuwe Setstrategy nu het standaard certificaatverificatieproces overschrijven (die een geconfigureerde trustmanager zou moeten raadplegen) - de test slaagt nu en de klant kan de HTTPS-URL gebruiken.

4. SSL configureren - Alles accepteren (HttpClient 4.4 en hoger)

Met de nieuwe HTTPClient hebben we nu een verbeterde, opnieuw ontworpen standaard SSL-hostnaamverificatie. Ook met de introductie van SSLConnectionSocketFactory en RegistryBuilder, is het eenvoudig om SSLSocketFactory te bouwen. Dus we kunnen de bovenstaande testcase schrijven als:

@Test openbare definitieve ongeldigheid gegevenAcceptingAllCertificates_whenHttpsUrlIsConsumed_thenOk () gooit GeneralSecurityException {urredtrategy acceptingTrustStrategy = (cert, authType) -> true; SSLContext sslContext = SSLContexts.custom (). LoadTrustMaterial (null, acceptingTrustStrategy) .build (); SSLConnectionSocketFactory sslsf = nieuwe SSLConnectionSocketFactory (sslContext, NoopHostnameVerifier.INSTANCE); Registry socketFactoryRegistry = RegistryBuilder. create () .register ("https", sslsf) .register ("http", nieuwe PlainConnectionSocketFactory ()) .build (); BasicHttpClientConnectionManager connectionManager = nieuwe BasicHttpClientConnectionManager (socketFactoryRegistry); CloseableHttpClient httpClient = HttpClients.custom (). SetSSLSocketFactory (sslsf) .setConnectionManager (connectionManager) .build (); HttpComponentsClientHttpRequestFactory requestFactory = nieuwe HttpComponentsClientHttpRequestFactory (httpClient); ResponseEntity response = nieuwe RestTemplate (requestFactory) .exchange (urlOverHttps, HttpMethod.GET, null, String.class); assertThat (response.getStatusCode (). value (), equalTo (200)); }

5. De lente RestTemplate met SSL (HttpClient <4.3)

Nu we hebben gezien hoe we een raw HttpClient met SSL-ondersteuning, laten we eens kijken naar een client op een hoger niveau - de lente RestTemplate.

Zonder SSL geconfigureerd, mislukt de volgende test zoals verwacht:

@Test (verwacht = ResourceAccessException.class) public void whenHttpsUrlIsConsumed_thenException () {String urlOverHttps = "// localhost: 8443 / httpclient-simple / api / bars / 1"; ResponseEntity response = nieuwe RestTemplate (). Exchange (urlOverHttps, HttpMethod.GET, null, String.class); assertThat (response.getStatusCode (). value (), equalTo (200)); }

Dus laten we SSL configureren:

@Test openbare ongeldige gegevenAcceptingAllCertificates_whenHttpsUrlIsConsumed_thenException () gooit GeneralSecurityException {HttpComponentsClientHttpRequestFactory requestFactory = nieuwe HttpComponentsClientHttpRequestFactory (); DefaultHttpClient httpClient = (DefaultHttpClient) requestFactory.getHttpClient (); Campsitetrategy acceptingTrustStrategy = (cert, authType) -> true SSLSocketFactory sf = nieuwe SSLSocketFactory (acceptingTrustStrategy, ALLOW_ALL_HOSTNAME_VERIFIER); httpClient.getConnectionManager (). getSchemeRegistry () .register (nieuw schema ("https", 8443, sf)); String urlOverHttps = "// localhost: 8443 / httpclient-simple / api / bars / 1"; ResponseEntity response = nieuwe RestTemplate (requestFactory). exchange (urlOverHttps, HttpMethod.GET, null, String.class); assertThat (response.getStatusCode (). value (), equalTo (200)); }

Zoals u kunt zien, is dit lijkt erg op de manier waarop we SSL hebben geconfigureerd voor de onbewerkte HttpClient - we configureren de aanvraagfabriek met SSL-ondersteuning en vervolgens instantiëren we de sjabloon die deze vooraf geconfigureerde fabriek passeert.

6. De lente RestTemplate met SSL (HttpClient 4.4)

En we kunnen op dezelfde manier onze RestTemplate:

@Test openbare ongeldige gegevenAcceptingAllCertificatesUsing4_4_whenUsingRestTemplate_thenCorrect () gooit ClientProtocolException, IOException {CloseableHttpClient httpClient = HttpClients.custom () .setSSLHostnameVerifier (nieuwe NoopHostname) .Verifier () HttpComponentsClientHttpRequestFactory requestFactory = nieuwe HttpComponentsClientHttpRequestFactory (); requestFactory.setHttpClient (httpClient); ResponseEntity response = nieuwe RestTemplate (requestFactory) .exchange (urlOverHttps, HttpMethod.GET, null, String.class); assertThat (response.getStatusCode (). value (), equalTo (200)); }

7. Conclusie

In deze tutorial werd besproken hoe SSL voor een Apache HttpClient moet worden geconfigureerd, zodat deze elke HTTPS-URL kan gebruiken, ongeacht het certificaat. Dezelfde configuratie voor de lente RestTemplate wordt ook geïllustreerd.

Een belangrijk ding om te begrijpen is echter dat deze strategie negeert certificaatcontrole volledig - waardoor het onveilig is en alleen te gebruiken waar dat zinvol is.

De implementatie van deze voorbeelden is te vinden in het GitHub-project - dit is een op Eclipse gebaseerd project, dus het moet gemakkelijk te importeren en uit te voeren zijn zoals het is.