httpclientbuilder example java ssl https apache-commons-httpclient

java - example - ¿Cómo forzar a Commons HTTPClient 3.1 a usar TLS 1.2 solo para HTTPS?



spring https client (3)

Deseo forzar al Cliente HTTP de Apache Commons (versión 3.1 ) a usar TLS 1.2 como el único protocolo para HTTPS.

Esto se debe a que el servidor supuestamente se actualizó a TLS 1.2 y ya no acepta ningún protocolo anterior (lo que hace que se devuelva ''Restablecimiento de la conexión'').

Para un contexto adicional, probablemente irrelevante, el Cliente HTTP se usa junto con Axis2 para hacer un SOAP; algunos de los códigos utilizados para configurar el HttpClient se encuentran a continuación:

MultiThreadedHttpConnectionManager connMgr = new MultiThreadedHttpConnectionManager(); this.httpClient = new HttpClient(connMgr); // initialize HttpClient parameters HttpClientParams hcParams = this.httpClient.getParams(); // Maximum time to wait to receive connection from pool hcParams.setConnectionManagerTimeout(this.maxWait); hcParams.setSoTimeout(this.timeout); hcParams.setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(this.retryCount, false)); // Initialize global Connection manager parameters HttpConnectionManagerParams cmParams = connMgr.getParams(); cmParams.setDefaultMaxConnectionsPerHost(this.maxActive); cmParams.setStaleCheckingEnabled(this.checkStaleConnections); cmParams.setConnectionTimeout(this.timeout);

¡Muchas gracias por la ayuda!


Depende de cómo escriba a sus clientes y qué versiones de JRE está utilizando:

Si está utilizando JRE8 (a menos que haya reemplazado el SunJSSE predeterminado que viene con JRE8), existe una propiedad del sistema "jdk.tls.client.protocols". De forma predeterminada, lo que mencione aquí se utilizará para todas las comunicaciones con los clientes.

Si está utilizando el objeto HttpsURLConnection para la conexión del cliente, puede usar la propiedad del sistema "https.protocols". Esto funcionará para todas las versiones de JRE, no solo para JRE8.

Si no especifica nada, para los clientes TLS, en JRE8, TLSv1, v1.1 y v1.2 están habilitados, por lo que funcionará con un servidor que admita cualquiera de estas versiones. Sin embargo, en JRE7, por defecto, TLSv1 solo está habilitado.

En su código, u siempre puede anular el valor predeterminado o lo que pasa a través de las propiedades del sistema. Lo que establezca en el código tendrá mayor prioridad. Para anular en el código ...

1) Si está utilizando el socket sin formato y SSLEngine, u puede configurar el protocolo y los cifrados en SSLEngine (sslEngine.setEnabledProtocols (..)

2) Si está utilizando SSLSocket, u puede configurar el protocolo y los cifrados en SSLSocket (sslSocket.setEnabledProtocols (..)

También puede obtener un SSLContext con el protocolo requerido habilitado y usarlo para cualquier componente SSL que use. SSLContext.getInstance ("TLSvx.x"). Tenga en cuenta que, de forma predeterminada, devolverá un contexto con todos los protocolos menos que TLSvx.x habilitado. Si ha configurado "jdk.tls.client.protocols", esto devolverá un contexto con esos protocolos habilitados.

No sería una buena idea codificar los protocolos en el código. Con bastante frecuencia, nos encontraremos con que ciertos clientes desean una versión específica, ya sea porque usan servidores antiguos o porque existen algunas vulnerabilidades graves en algunas versiones de TLS. Puede configurarlo a través de las propiedades del sistema o incluso si está configurando explícitamente en sslsocket o sslengine, lea esto en algún archivo conf.

Consulte también:

https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html

http://docs.oracle.com/javase/8/docs/technotes/guides/security/SunProviders.html


Lástima que nadie contestó; Pude hacerlo, primero escribes un CustomHttpSocketFactory , luego lo haces:

String scheme = "https"; Protocol baseHttps = Protocol.getProtocol(scheme); int defaultPort = baseHttps.getDefaultPort(); ProtocolSocketFactory baseFactory = baseHttps.getSocketFactory(); ProtocolSocketFactory customFactory = new CustomHttpsSocketFactory(baseFactory); Protocol customHttps = new Protocol(scheme, customFactory, defaultPort); Protocol.registerProtocol(scheme, customHttps);

here se encuentra un ejemplo de código de fábrica de sockets personalizados, pero en su lugar lo hice:

public class CustomHttpsSocketFactory implements SecureProtocolSocketFactory { private final SecureProtocolSocketFactory base; public CustomHttpsSocketFactory(ProtocolSocketFactory base) { if(base == null || !(base instanceof SecureProtocolSocketFactory)) throw new IllegalArgumentException(); this.base = (SecureProtocolSocketFactory) base; } private Socket acceptOnlyTLS12(Socket socket) { if(!(socket instanceof SSLSocket)) return socket; SSLSocket sslSocket = (SSLSocket) socket; sslSocket.setEnabledProtocols(new String[]{"TLSv1.2" }); return sslSocket; } @Override public Socket createSocket(String host, int port) throws IOException { return acceptOnlyTLS12(base.createSocket(host, port)); } @Override public Socket createSocket(String host, int port, InetAddress localAddress, int localPort) throws IOException { return acceptOnlyTLS12(base.createSocket(host, port, localAddress, localPort)); } @Override public Socket createSocket(String host, int port, InetAddress localAddress, int localPort, HttpConnectionParams params) throws IOException { return acceptOnlyTLS12(base.createSocket(host, port, localAddress, localPort, params)); } @Override public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException { return acceptOnlyTLS12(base.createSocket(socket, host, port, autoClose)); } }


Necesitas una referencia de Socket en tu código. Entonces puedes configurar protocolos habilitados en esto de esta manera:

if (socket != null && (socket instanceof SSLSocket)) { ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.2"}); }