I recently added LetsEncrypt certificates to my server and my java applet is having problems connecting using TLS.
My applet uses Apache HttpClient.
My web s
I was getting the same error when I was using methods from org.apache.http.* for making my http requests. From your stack trace I assume that even you are using the same.
This error disappeared when I used java.net.HttpURLConnection and I was able to connect successfully.
import java.net.HttpURLConnection;
public static HttpURLConnection connectToWeb(String uri) {
HttpURLConnection connection = null;
try {
URL url = new URL(uri);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.connect();
} catch (MalformedURLException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
return connection;
}
Following Yurri's comment, it solved my problem by adding NoopHostnameVerifier.INSTANCE while initialising SSLConnectionSocketFactory :
import org.apache.http.HttpHost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.TrustStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import java.net.Proxy;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import javax.net.ssl.SSLContext;
/**
* Provide basic Utils for getting HttpHeader and making REST api calls.
*
*/
@Component
public class HttpUtil {
private static final Logger LOG = LoggerFactory.getLogger(HttpUtil.class);
/**
* The default implementation to get basic headers.
* @return HttpHeaders.
*/
public HttpHeaders getHttpHeaders(String userAgent, String host) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set(HttpHeaders.ACCEPT_CHARSET, StandardCharsets.UTF_8.name());
headers.set(HttpHeaders.USER_AGENT, userAgent);
LOG.info("host=" + host);
if (null != host) {
headers.set(HttpHeaders.HOST, host);
}
return headers;
}
/**
* Default implementation to get RestTemplate
* @return
*/
public RestTemplate getRestTemplate(String proxyHost, int proxyPort)
throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
TrustStrategy acceptingTrustStrategy = new TrustSelfSignedStrategy();
SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy)
.build();
SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(csf).build();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
if (null != proxyHost && proxyPort > 0) {
LOG.info("PROXY CONFIGURED | proxyHost=" + proxyHost + " | proxyPort=" + proxyPort);
HttpHost proxy = new HttpHost(proxyHost, proxyPort, Proxy.Type.HTTP.name());
httpClient = HttpClients.custom().setSSLSocketFactory(csf)
.setRoutePlanner(new DefaultProxyRoutePlanner(proxy)).build();
}
requestFactory.setHttpClient(httpClient);
RestTemplate restTemplate = new RestTemplate(requestFactory);
return restTemplate;
}
/**
* Make a rest api call
* @return ResponseEntity
*/
public ResponseEntity<String> getApiResponse(HttpMethod httpMethod, final String URL, final String userAgent,
String proxyHost, int proxyPort, String host) throws HttpClientErrorException {
ResponseEntity<String> response = null;
HttpEntity<String> httpEntity = new HttpEntity<>(getHttpHeaders(userAgent, host));
try {
if (null != httpMethod && null != URL) {
RestTemplate request = null;
try {
request = getRestTemplate(proxyHost, proxyPort);
response = request.exchange(URL, httpMethod, httpEntity, String.class);
} catch (KeyManagementException | KeyStoreException | NoSuchAlgorithmException e) {
LOG.error("Error creating Rest Template", e);
}
}
} catch (HttpClientErrorException ex) {
LOG.error("Method = " + httpMethod.toString() + "Request URL = " + URL);
LOG.error("Headers =" + getHttpHeaders(userAgent, host));
LOG.error("Response Status = " + ex.getStatusText());
LOG.error("Response Body = " + ex.getResponseBodyAsString());
throw ex;
}
return response;
}
}
I don't know which version of the Apache HttpClient you were using but versions 4.4.1 and 4.5.1 had a bug where the SNI didn't work correctly. This was fixed in 4.5.3
https://issues.apache.org/jira/browse/HTTPCLIENT-1726
If you use HttpClient 4.4 then you need to specify host verifier (NoopHostnameVerifier) to allow accepting certificates from different hosts:
SSLConnectionSocketFactory scsf = SSLConnectionSocketFactory(
SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build(),
NoopHostnameVerifier.INSTANCE)
httpclient = HttpClients.custom().setSSLSocketFactory(scsf).build()
/*
* Inner class for Proxy SSL Socket Connection.
*/
static class MyConnectionSocketFactory extends SSLConnectionSocketFactory {
private String proxyHost = null;
private Integer proxyPort = null;
public MyConnectionSocketFactory(final SSLContext sslContext, String proxyHost, Integer proxyPort) {
super(sslContext, new NoopHostnameVerifier());
this.proxyHost = proxyHost;
this.proxyPort = proxyPort;
}
@Override
public Socket createSocket(final HttpContext context) throws IOException {
logger.debug("Create Socket:" + " ProxyHost: " + proxyHost + ", ProxyPort: " + proxyPort);
InetSocketAddress socksaddr = new InetSocketAddress(proxyHost,proxyPort);
Proxy proxy = new Proxy(Proxy.Type.SOCKS, socksaddr);
return new Socket(proxy);
}
}
else if (proxyType.equalsIgnoreCase("socks")) {
logger.debug("Proxy Type: " + proxyType);
TrustStrategy acceptingTrustStrategy = new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
return true;
}
};
SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom()
.loadTrustMaterial(null, acceptingTrustStrategy)
.build();
SSLConnectionSocketFactory csf = new MyConnectionSocketFactory(sslContext, proxyHost, proxyPort);
CloseableHttpClient httpClient = HttpClients.custom()
.setSSLSocketFactory(csf)
.build();
HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
restTemplate = new RestTemplate(requestFactory);
return;
} else {