Отключение или обход проверки сертификата SSL никогда не является рекомендуемым решением для проблем SSL, но в тестовой среде иногда это может понадобиться. В этом руководстве я создаю экземпляры org.apache.http.impl.client.DefaultHttpClient, доступные до версии Apache HTTP Library 4.2, и org.apache.http.impl.client.CloseableHttpClient, доступные с версии Apache HTTP Library 4.3.
DefaultHttpClient теперь является устаревшим классом, поэтому предлагается использовать класс CloseableHttpClient. Пожалуйста, помните, что обходить проверку SSL следует только в целях отладки, когда мы хотим протестировать несколько защищенных API без настройки установки сертификата на локальной машине.
1. Обход проверки SSL-сертификата с помощью CloseableHttpClient
Если вы работаете с последними версиями библиотеки Apache HTTP, вам следует использовать эту версию кода.
public static CloseableHttpClient getCloseableHttpClient(){CloseableHttpClient httpClient = null;try {httpClient = HttpClients.custom().setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).setSSLContext(new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy(){public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException{return true;}}).build()).build();} catch(KeyManagementException e) {LOGGER.error("KeyManagementException in creating http client instance", e);} catch(NoSuchAlgorithmException e) {LOGGER.error("NoSuchAlgorithmException in creating http client instance", e);} catch(KeyStoreException e) {LOGGER.error("KeyStoreException in creating http client instance", e);}return httpClient;}
Чтобы использовать экземпляр CloseableHttpClient, используйте его следующим образом.
//Some custom method to craete HTTP post objectHttpPost post = createPostRequest();//Get http clientCloseableHttpClient httpClient = getCloseableHttpClient();//Execute HTTP methodCloseableHttpResponse res = httpClient.execute(post);//Verify responseif(res.getStatusLine().getStatusCode() == 200){String json = EntityUtils.toString(res.getEntity());}
2. Обход проверки SSL-сертификата с помощью DefaultHttpClient
Если вы работаете со старыми версиями библиотеки Apache HTTP, вам следует использовать эту версию кода.
public static DefaultHttpClient getDefaultHttpClient() throws Exception{DefaultHttpClient httpClient = new DefaultHttpClient();SSLContext ssl_ctx = SSLContext.getInstance("TLS");TrustManager[] certs = new TrustManager[] { new X509TrustManager() {public X509Certificate[] getAcceptedIssuers() {return null;}public void checkClientTrusted(X509Certificate[] certs, String t) {}public void checkServerTrusted(X509Certificate[] certs, String t) {}} };ssl_ctx.init(null, certs, new SecureRandom());SSLSocketFactory ssf = new SSLSocketFactory(ssl_ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);ClientConnectionManager ccm = httpClient.getConnectionManager();SchemeRegistry sr = ccm.getSchemeRegistry();sr.register(new Scheme("https", 443, ssf));return new DefaultHttpClient(ccm, httpClient.getParams());}
Чтобы использовать экземпляр DefaultHttpClient, используйте его следующим образом.
//Some custom method to craete HTTP post objectHttpPost post = createPostRequest();//Get http clientDefaultHttpClient client = getDefaultHttpClient();//Execute HTTP methodHttpResponse httpResponse = client.execute(post);//Handle response
Еще раз, пожалуйста, не используйте его в производственной среде, поскольку это сводит на нет весь смысл обеспечения безопасности SSL.
3. Настройте Spring RestTemplate
Если мы используем этот код в приложении Spring, мы можем настроить bean-компонент RestTemplate следующим образом. Не забудьте закомментировать этот код при переходе в производство.
@Configurationpublic class RestTemplateSSLBypassConfig {@Beanpublic RestTemplate restTemplate() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {TrustStrategy acceptingTrustStrategy =(X509Certificate[] chain, String authType) -> true;SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(csf).build();HttpComponentsClientHttpRequestFactory requestFactory =new HttpComponentsClientHttpRequestFactory();requestFactory.setHttpClient(httpClient);RestTemplate restTemplate = new RestTemplate(requestFactory);return restTemplate;}}
4. Настройте Spring WebClient
Мы также можем настроить WebClient, который использует небезопасный InsecureTrustManagerFactory, следующим образом:
@Beanpublic WebClient createWebClient() throws SSLException {SslContext sslContext = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();HttpClient httpClient = HttpClient.create().secure(t -> t.sslContext(sslContext));return WebClient.builder().clientConnector(new ReactorClientHttpConnector(httpClient)).build();}
5. Возможное сообщение об исключении SSLHandshakeException
Если вы не настроили код выше правильно, вы можете найти сообщение об исключении ниже. Это сообщение подтверждает, что сопоставление сертификата SSL все еще не удается.
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: не удалось построить путь PKIX: sun.security.provider.certpath.SunCertPathBuilderException: не удалось найти допустимый путь сертификации к запрошенной целив sun.security.ssl.Alerts.getSSLException(Alerts.java:192)в sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1916)в sun.security.ssl.Handshaker.fatalSE(Handshaker.java:279)в sun.security.ssl.Handshaker.fatalSE(Handshaker.java:273)в sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1472)в sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:213)в sun.security.ssl.Handshaker.processLoop(Handshaker.java:913)в sun.security.ssl.Handshaker.process_record(Handshaker.java:849)в sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1035)в sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1344)в sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1371)в sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1355)в org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:394)в org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:353)в org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:141)в org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353)в org.apache.http.impl.execchain.MainClientExec.installRoute(MainClientExec.java:380)в org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)в org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)в org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)в org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)в org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)в org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)в org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
Пишите мне свои вопросы в комментариях.