HttpClient med SSL

1. Oversigt

Denne artikel viser, hvordan man gør det konfigurer Apache HttpClient 4 med "Accepter alt" SSL-understøttelse. Målet er simpelt - forbrug HTTPS-URL'er, der ikke har gyldige certifikater.

Hvis du vil grave dybere og lære andre seje ting, kan du gøre med HttpClient - gå videre til den vigtigste HttpClient-guide.

2. Den SSLPeerUnverifiedException

Uden at konfigurere SSL med HttpClient, den følgende test - forbrugende en HTTPS URL - mislykkes:

offentlig klasse RestClientLiveManualTest {@Test (forventet = SSLPeerUnverifiedException.class) offentlig ugyldig nårHttpsUrlIsConsumed_thenException () kaster ClientProtocolException, IOException {CloseableHttpClient httpClient = HttpClients.createDefault; String urlOverHttps = "// localhost: 8082 / httpclient-simple"; HttpGet getMethod = ny HttpGet (urlOverHttps); HttpResponse respons = httpClient.execute (getMethod); assertThat (respons.getStatusLine (). getStatusCode (), equalTo (200)); }}

Den nøjagtige fiasko er:

javax.net.ssl.SSLPeerUnverifiedException: peer ikke godkendt på sun.security.ssl.SSLSessionImpl.getPeerCertificates (SSLSessionImpl.java:397) på org.apache.http.conn.ssl.AbstractVerifier.verify (AbstractVerifier.java12) ..

Det javax.net.ssl.SSLPeerUnverifiedException undtagelse opstår, når en gyldig kæde af tillid ikke kunne oprettes for URL'en.

3. Konfigurer SSL - Accepter alle (HttpClient <4.3)

Lad os nu konfigurere HTTP-klienten til at stole på alle certifikatkæder uanset deres gyldighed:

@Test offentlig endelig ugyldighed givenAcceptingAllCertificates_whenHttpsUrlIsConsumed_thenOk () kaster GeneralSecurityException {HttpComponentsClientHttpRequestFactory requestFactory = ny HttpComponentsClientHttpRequestFactory (); CloseableHttpClient httpClient = (CloseableHttpClient) requestFactory.getHttpClient (); TrustStrategy acceptingTrustStrategy = (cert, authType) -> true; SSLSocketFactory sf = ny SSLSocketFactory (acceptererTrustStrategy, ALLOW_ALL_HOSTNAME_VERIFIER); httpClient.getConnectionManager (). getSchemeRegistry (). register (nyt skema ("https", 8443, sf)); ResponseEntity response = ny RestTemplate (requestFactory). exchange (urlOverHttps, HttpMethod.GET, null, String.class); assertThat (respons.getStatusCode (). værdi (), equalTo (200)); }

Med det nye TrustStrategy nu tilsidesættelse af standardcertifikatbekræftelsesprocessen (som skal konsultere en konfigureret tillidsmanager) - testen består nu og klienten er i stand til at forbruge HTTPS URL.

4. Konfigurer SSL - Accepter alle (HttpClient 4.4 og derover)

Med den nye HTTPClient har vi nu en forbedret, redesignet standard SSL-værtsnavnverifikator. Også med introduktionen af SSLConnectionSocketFactory og RegistryBuilder, det er let at opbygge SSLSocketFactory. Så vi kan skrive ovenstående testsag som:

@Test offentlig endelig ugyldighed givenAcceptingAllCertificates_whenHttpsUrlIsConsumed_thenOk () kaster GeneralSecurityException {TrustStrategy acceptingTrustStrategy = (cert, authType) -> true; SSLContext sslContext = SSLContexts.custom (). LoadTrustMaterial (null, acceptingTrustStrategy) .build (); SSLConnectionSocketFactory sslsf = ny SSLConnectionSocketFactory (sslContext, NoopHostnameVerifier.INSTANCE); Registry socketFactoryRegistry = RegistryBuilder. Opret () .register ("https", sslsf) .register ("http", ny PlainConnectionSocketFactory ()) .build (); BasicHttpClientConnectionManager connectionManager = ny BasicHttpClientConnectionManager (socketFactoryRegistry); CloseableHttpClient httpClient = HttpClients.custom (). SetSSLSocketFactory (sslsf) .setConnectionManager (connectionManager) .build (); HttpComponentsClientHttpRequestFactory requestFactory = ny HttpComponentsClientHttpRequestFactory (httpClient); ResponseEntity response = ny RestTemplate (requestFactory). Udveksling (urlOverHttps, HttpMethod.GET, null, String.class); assertThat (respons.getStatusCode (). værdi (), equalTo (200)); }

5. Foråret RestTemplate med SSL (HttpClient <4.3)

Nu hvor vi har set, hvordan man konfigurerer en rå HttpClient med SSL-support, lad os se på en højere klient - foråret RestTemplate.

Uden SSL konfigureret mislykkes følgende test som forventet:

@Test (forventet = ResourceAccessException.class) offentlig ugyldig nårHttpsUrlIsConsumed_thenException () {String urlOverHttps = "// localhost: 8443 / httpclient-simple / api / bars / 1"; ResponseEntity respons = ny RestTemplate (). Udveksling (urlOverHttps, HttpMethod.GET, null, String.class); assertThat (respons.getStatusCode (). værdi (), equalTo (200)); }

Så lad os konfigurere SSL:

@Test offentlig ugyldighed givenAcceptingAllCertificates_whenHttpsUrlIsConsumed_thenException () kaster GeneralSecurityException {HttpComponentsClientHttpRequestFactory requestFactory = ny HttpComponentsClientHttpRequestFactory (); DefaultHttpClient httpClient = (DefaultHttpClient) requestFactory.getHttpClient (); TrustStrategy acceptingTrustStrategy = (cert, authType) -> true SSLSocketFactory sf = new SSLSocketFactory (acceptingTrustStrategy, ALLOW_ALL_HOSTNAME_VERIFIER); httpClient.getConnectionManager (). getSchemeRegistry () .register (ny skema ("https", 8443, sf)); String urlOverHttps = "// localhost: 8443 / httpclient-simple / api / bars / 1"; ResponseEntity response = ny RestTemplate (requestFactory). exchange (urlOverHttps, HttpMethod.GET, null, String.class); assertThat (respons.getStatusCode (). værdi (), equalTo (200)); }

Som du kan se, er dette meget lig den måde, vi konfigurerede SSL til den rå HttpClient - vi konfigurerer anmodningsfabrikken med SSL-understøttelse, og derefter instantierer vi skabelonen, der passerer denne forudkonfigurerede fabrik.

6. Foråret RestTemplate med SSL (HttpClient 4.4)

Og vi kan bruge samme måde til at konfigurere vores RestTemplate:

@Test offentlig ugyldighed givenAcceptingAllCertificatesUsing4_4_whenUsingRestTemplate_thenCorrect () kaster ClientProtocolException, IOException {CloseableHttpClient httpClient = HttpClients.custom () .setSSLHostnameVerifier (new NoopHost.) HttpComponentsClientHttpRequestFactory requestFactory = ny HttpComponentsClientHttpRequestFactory (); requestFactory.setHttpClient (httpClient); ResponseEntity response = ny RestTemplate (requestFactory). Udveksling (urlOverHttps, HttpMethod.GET, null, String.class); assertThat (respons.getStatusCode (). værdi (), equalTo (200)); }

7. Konklusion

Denne vejledning diskuterede, hvordan man konfigurerer SSL til en Apache HttpClient, så den er i stand til at forbruge enhver HTTPS-URL, uanset certifikatet. Den samme konfiguration for foråret RestTemplate er også illustreret.

En vigtig ting at forstå er dog, at denne strategi ignorerer fuldstændigt certifikatkontrol - hvilket gør det usikkert og kun bruges, hvor det giver mening.

Implementeringen af ​​disse eksempler findes i GitHub-projektet - dette er et Eclipse-baseret projekt, så det skal være let at importere og køre som det er.