2015-09-15 8 views
18

desidero forzare Apache Commons HTTP-client (versione 3.1 ) per utilizzare TLS 1.2 come solo protocollo per HTTPS.Come forzare Commons HTTPClient 3.1 per utilizzare TLS 1.2 solo per HTTPS?

Ciò è dovuto al fatto che il server è stato aggiornato a TLS 1.2 e non accetta più alcun protocollo precedente (causando la restituzione di "Reset connessione").

Per ulteriore contesto, probabilmente irrilevante, il client HTTP viene utilizzato insieme a Axis2 per creare un SOAP; parte del codice utilizzato per impostare HttpClient è il seguente:

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

Grazie mille per l'aiuto!

+0

Dal momento che si sta utilizzando questo software vecchio e non mantenuto presumo che si sta utilizzando una vecchia versione di Java troppo. Sei sicuro che Java sia in grado di parlare Java 1.2 (quale versione di Java usi?) –

+0

No, sto usando Java 7 e il codice non è troppo vecchio, funziona abbastanza bene fino ad ora. –

risposta

20

Peccato che nessuno abbia risposto; Sono stato in grado di farlo, prima si scrive un CustomHttpSocketFactory, poi si fa: codice di fabbrica

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

Una presa personalizzato campione viene trovato here, ma invece ho fatto:

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

} 
+0

'SecureProtocolSocketFactory' è diverso da' SSLSocketFactory'? –

+1

SecureProtocolSocketFactory è un'interfaccia in HTTPClient di Apache utile per implementare un factory socket personalizzato; I ** credo ** SSLSocketFactory di java sarebbe meno utile in questo caso. –

+0

@ united-expression Ho lo stesso requisito tranne che sto usando HTTP-Client (versione 4.1). Il tuo codice è utile anche se non sono ancora chiaro dove stai vincendo httpClient con questo protocollo registrato? – LoveForDroid

2

Hai bisogno di un riferimento Socket nel codice. Quindi è possibile impostare abilitato protocolli su come questo:

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

Dipende da come si sta scrivendo i vostri clienti e quali versioni di JRE che si sta utilizzando:

Se si utilizza JRE8 (a meno che non hanno sostituito il SunJSSE predefinito fornito con JRE8), esiste una proprietà di sistema "jdk.tls.client.protocols". Per impostazione predefinita, qualsiasi cosa menzionata qui verrà utilizzata per tutte le comunicazioni client.

Se si utilizza l'oggetto HttpsURLConnection per la connessione client, è possibile utilizzare la proprietà di sistema "https.protocols". Questo funzionerà per tutte le versioni di JRE, non solo per JRE8.

Se non si specifica nulla, per i client TLS, in JRE8, TLSv1, v1.1 e v1.2 sono abilitati, quindi funzionerà con un server che supporta una qualsiasi di queste versioni. Tuttavia, in JRE7, per impostazione predefinita TLSv1 è abilitato.

Nel codice, è sempre possibile ignorare il valore predefinito o quello che si passa attraverso le proprietà del sistema. Quello che hai impostato nel codice avrà maggiore precedenza. Per sostituire nel codice ...

1) Se si utilizza raw socket e SSLEngine, u possibile impostare il protocollo e cifre nel SSLEngine (sslEngine.setEnabledProtocols (..)

2) Se si è utilizzando SSLSocket, puoi impostare il protocollo e le crittografie nel SSLSocket (sslSocket.setEnabledProtocols (..)

Puoi anche ottenere un SSLContext con il protocollo richiesto abilitato e utilizzarlo per qualsiasi componente SSL che usi. SSLContext.getInstance ("TLSvx.x"). Si noti che per impostazione predefinita verrà restituito un contesto con tutti i protocolli minori di TLSvx.x abilitato.Se si è configurato "jdk.tls.client.protocols", verrà restituito un contesto con tali protocolli abilitati .

Non sarebbe una buona idea codificare i protocolli nel codice. Molto spesso, incontreremo alcuni clienti che desiderano una versione specifica perché utilizzano server vecchi o si riscontrano alcune gravi vulnerabilità in alcune versioni di TLS. O impostalo tramite le proprietà del sistema o anche se stai impostando esplicitamente in sslsocket o sslengine, leggi quello da qualche file conf.

riferiscono anche:

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