Comment forcer Commons HTTPClient 3.1 à utiliser TLS 1.2 uniquement pour HTTPS?

je tiens à la force Apache Commons HTTP-Client(version 3.1) pour utiliser TLS 1.2 protocole pour HTTPS.

ceci est dû au fait que le serveur est supposé être mis à jour à TLS 1.2 et n'accepte plus aucun protocole plus ancien (ce qui fait que 'connexion Reset' doit être retourné).

pour plus de contexte, probablement hors de propos, le client HTTP est utilisé avec Axis2 pour faire un SOAP; voici une partie du code utilisé pour configurer HttpClient:

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);

Merci beaucoup pour l'aide!

19
demandé sur united-expression 2015-09-15 16:16:49

3 réponses

dommage que personne n'ait répondu; j'ai pu le faire, d'abord vous écrivez un CustomHttpSocketFactory, puis tu fais:

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); 

un exemple de code d'usine de socket personnalisé est trouvé ici, mais à la place j'ai fait:

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));
   }

}
26
répondu united-expression 2015-09-16 10:20:19

Vous avez besoin d'une référence Socket dans votre code. Ensuite, vous pouvez définir les Protocoles activés comme ceci:

if (socket != null && (socket instanceof SSLSocket)) {
    ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.2"});
}
2
répondu Igor Ganapolsky 2016-04-21 14:05:48

cela dépend de la façon dont vous écrivez vos clients et des versions JRE que vous utilisez:

si vous utilisez Jre8 (sauf si vous avez remplacé le SunJSSE par défaut qui est livré avec JRE8), il y a une propriété système "jdk.tls.client.protocole." Par défaut, tout ce que vous mentionnez ici sera utilisé pour toute communication client.

si vous utilisez L'objet HttpsURLConnection pour la connexion client, vous pouvez utiliser la propriété système "https.protocole." Cela fonctionnera pour tous les JRE versions, pas seulement JRE8.

si vous ne spécifiez rien, pour les clients TLS, dans JRE8, TLSv1, v1.1 et v1.2 sont activés, donc il fonctionnera avec un serveur qui supporte n'importe laquelle de ces versions. Cependant dans JRE7 par défaut TLSv1 seul est activé.

dans votre code u peut toujours outrepasser la valeur par défaut ou ce que u passe à travers les propriétés du système. Ce que vous mettez dans le code aura priorité. De remplacer dans le code...

1) Si vous utilisez le socket brut et SSLEngine, u peut définir le protocole et les chiffreurs dans le SSLEngine (sslEngine.setEnabledProtocols(..)

2) Si vous utilisez SSLSocket, vous pouvez configurer le protocole et les chiffreurs dans SSLSocket (sslSocket.setEnabledProtocols(..)

vous pouvez également obtenir un texte SSL avec le protocole requis activé et l'utiliser pour tous les composants SSL que vous utilisez. SSLContext.gettinstance ("TLSvx.x"). Notez que par défaut il retournera un contexte avec tous les protocoles inférieurs à TLSvx.x activé. Si vous avez configuré " jdk.tls.client.protocoles", cela renverra à un contexte avec ces Protocoles activés.

ce ne serait pas une bonne idée de codifier les protocoles dans le code. Très souvent, nous rencontrons certains clients qui veulent une version spécifique, soit parce qu'ils utilisent d'anciens serveurs, soit parce que certaines vulnérabilités graves sont rencontrées dans certaines versions de TLS. Soit le définir par les propriétés du système, soit même si vous le définissez explicitement dans sslsocket ou sslengine, lisez cela de certains fichier conf.

voir aussi:

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

2
répondu Rajesh 2016-08-12 15:06:21