On Tue, 2013-10-08 at 00:24 +0000, Pete Keyes wrote:
> We're using http-client 4.3 and have some situation where the EDI trading
> partner HTTP server presents an SSL certificate with a CN doesn't match the
> service URL's hostname. To support this we're trying to use the following
> code to override the default http-client "BrowserCompatHostnameVerifier"
> strategy on a case-by-case basis:
> private static final PoolingHttpClientConnectionManager connManager =
> new PoolingHttpClientConnectionManager()
> ;
> connManager.setDefaultMaxPerRoute(10);
> connManager.setMaxTotal(5000);
>
> final RequestConfig requestConfig = RequestConfig.custom()
> .setAuthenticationEnabled(bsc.getBasicAuthCfg().isEnabled())
> .setConnectTimeout(bsc.getConnTimeoutMs())
> .setExpectContinueEnabled(bsc.isExpectContinue())
> .setSocketTimeout(bsc.getSoTimeoutMs())
> .setStaleConnectionCheckEnabled(bsc.isStaleConnCheck())
> .build()
> ;
>
> final HttpHost httpHost = new HttpHost(
> bsc.getUrl().getHost(), bsc.getUrl().getPort()
> );
> final HttpRoute httpRoute = new HttpRoute(httpHost);
> AbstractHttpDeliverTDB.connManager.setMaxPerRoute(
> httpRoute, bsc.getMaxConns()
> );
> final HttpClientBuilder builder = HttpClients.custom()
> .setConnectionManager(AbstractHttpDeliverTDB.connManager)
> .setDefaultConnectionConfig(
> ConnectionConfig.custom().setCharset(charset).build()
> )
> .setDefaultRequestConfig(requestConfig)
> ;
>
> // disable hostname verification ... if option is disabled
> if(!bsc.isVerifySSLHostname()) {
> StringBuilder msg = new StringBuilder(100)
> .append("hostname verification disabled in http config:")
> .append(" env-id=").append(envId.name())
> .append("; tp=").append(partnerId)
> .append("; tx=").append(folderNm)
> .append("; cfg-nm=").append(cfgDocNm)
> ;
> log.warn(msg);
> final SSLContext sslContext = SSLContexts.createSystemDefault();
> final SSLConnectionSocketFactory sslSF = new
> SSLConnectionSocketFactory(
> sslContext
> , SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
> );
> builder.setSSLSocketFactory(sslSF);
> }
>
> CloseableHttpClient httpClient = builder.build();
>
> final HttpClientContext httpContext = HttpClientContext.create();
>
> // add login form parameters
> UrlEncodedFormEntity urlEntity = new UrlEncodedFormEntity(
> formDataList
> , context.bscBase.getCharset()
> );
>
> // execute login service to get session token
> HttpPost request = new HttpPost(urlLogin);
> request.setEntity(urlEntity);
> HttpResponse response = httpClient.execute(request, httpContext);
>
> The code above results in http-client using the browser compatible strategy
> rather than simply ignoring the hostname verification as desired.
> 10-07 17:00:06.856|FATAL|us bams - 12|
> |SBaseDeliverTDB.login(BAMSBaseDeliverTDB.java:351)|bams login failed:
> https://nonp-glbl-bam/m3oui/rest/login; err=javax.net.ssl.SSLException:
> hostname in certificate didn't match: <nonp-glbl-bam> !=
> <nonp-glbl-bam.starbucks.net>
> javax.net.ssl.SSLException: hostname in certificate didn't match:
> <nonp-glbl-bam> != <nonp-glbl-bam.starbucks.net>
> at
> org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:232)
> ~[apache-httpclient-4.3.jar:4.3]
> at
> org.apache.http.conn.ssl.BrowserCompatHostnameVerifier.verify(BrowserCompatHostnameVerifier.java:54)
> ~[apache-httpclient-4.3.jar:4.3]
> at
> org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:152)
> ~[apache-httpclient-4.3.jar:4.3]
> at
> org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:133)
> ~[apache-httpclient-4.3.jar:4.3]
> at
> org.apache.http.conn.ssl.SSLConnectionSocketFactory.verifyHostname(SSLConnectionSocketFactory.java:289)
> ~[apache-httpclient-4.3.jar:4.3]
> at
> org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:263)
> ~[apache-httpclient-4.3.jar:4.3]
> at
> org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:118)
> ~[apache-httpclient-4.3.jar:4.3]
> at
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:314)
> ~[apache-httpclient-4.3.jar:4.3]
> at
> org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:357)
> ~[apache-httpclient-4.3.jar:4.3]
> at
> org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:218)
> ~[apache-httpclient-4.3.jar:4.3]
> at
> org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:194)
> ~[apache-httpclient-4.3.jar:4.3]
> at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:85)
> ~[apache-httpclient-4.3.jar:4.3]
> at
> org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
> ~[apache-httpclient-4.3.jar:4.3]
> at
> org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:186)
> ~[apache-httpclient-4.3.jar:4.3]
> at
> org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
> ~[apache-httpclient-4.3.jar:4.3]
>
> I'm assuming we've missed something basic in the process of trying to
> override hostname verification on a client-by-client basis. Can anyone point
> out where we've messed up?
>
> ...Pete
>
Pete,
In your case a custom connection manager overrides a custom hostname
verifier. You cannot have them both.
If you have a list of hosts you would like to handle differently prior
to constructing the connection manager you should create a custom
X509HostnameVerifier and supply to the connection manager at the
construction time. If you want to update the list dynamically your only
option is to create a custom LayeredConnectionSocketFactory and use
HttpContext to supply the list of special cases to the #connectSocket
method.
Hope this helps
Oleg
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]