2015-09-15 4 views
18

Ich möchte zwingen Apache Commons HTTP-Client- (Version 3.1 ) für HTTPS TLS 1.2 als nur Protokoll zu verwenden.Wie Commons HTTPClient 3.1 zwingen, TLS 1.2 nur für HTTPS zu verwenden?

Dies liegt daran, dass der Server angeblich auf TLS 1.2 aktualisiert wurde und kein älteres Protokoll mehr akzeptiert (wodurch "Connection Reset" zurückgegeben wird).

Für weiteren Kontext, wahrscheinlich irrelevant, wird der HTTP-Client zusammen mit Axis2 verwendet, um einen SOAP zu erstellen; einige der Code für die Einrichtung der HttpClient ist unten:

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

Vielen Dank für die Hilfe!

+0

Da Sie diese alte und unmaintained Software verwenden Ich gehe davon aus, dass Sie eine alte Java-Version zu verwenden. Sind Sie sicher, dass Ihr Java überhaupt in der Lage ist Java 1.2 zu sprechen (d. H. Welche Version von Java benutzen Sie?) –

+0

Nein, ich benutze Java 7, und der Code ist nicht zu alt, er funktioniert bis jetzt ziemlich gut. –

Antwort

20

Schade, niemand antwortete; Ich war in der Lage, es zu tun, zuerst schreiben Sie eine CustomHttpSocketFactory, dann tun Sie:

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

Eine Probe benutzerdefinierte Socket-Factory-Code wird here gefunden, sondern ich tat:

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

Ist 'SecureProtocolSocketFactory' von' SSLSocketFactory' verschieden? –

+1

SecureProtocolSocketFactory ist eine Schnittstelle in Apache HTTPClient hilfreich für die Implementierung einer benutzerdefinierten Socket-Factory; Ich glaube, dass javas SSLSocketFactory in diesem Fall weniger hilfreich wäre. –

+0

@ united-expression Ich habe die gleiche Anforderung, außer dass ich HTTP-Client (Version 4.1) verwende. Ihr Code ist hilfreich, aber ich bin immer noch nicht klar, wo binden Sie httpClient mit diesem registrierten Protokoll? – LoveForDroid

2

Sie benötigen eine Socket-Referenz in Ihrem Code. Dann können Sie Protokolle auf es so Satz aktiviert:

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

Es hängt davon ab, wie Sie Ihre Kunden schreiben und was JRE-Versionen Sie verwenden:

Wenn Sie mit JRE8 (es sei denn, Sie ersetzt die Standard SunJSSE, die mit JRE8 geliefert wird), gibt es eine Systemeigenschaft "jdk.tls.client.protocols". Standardmäßig wird alles, was Sie hier angeben, für die gesamte Client-Kommunikation verwendet.

Wenn Sie das HttpsURLConnection-Objekt für die Clientverbindung verwenden, können Sie die Systemeigenschaft "https.protocols" verwenden. Dies funktioniert für alle JRE-Versionen, nicht nur für JRE8.

Wenn Sie für TLS-Clients nichts angeben, sind JRE8, TLSv1, v1.1 und v1.2 aktiviert, sodass es mit einem Server funktioniert, der eine dieser Versionen unterstützt. In JRE7 ist TLSv1 jedoch standardmäßig aktiviert.

In Ihrem Code können Sie den Standard überschreiben oder die Systemeigenschaften durchlaufen. Was du im Code eingibst, hat eine höhere Priorität. Um im Code außer Kraft setzen ...

1) Wenn Sie Raw-Socket und SSLEngine verwenden, kann u das Protokoll und Chiffren im SSLEngine (sslEngine.setEnabledProtocols (..) gesetzt

2) Wenn Sie Mithilfe von SSLSocket können Sie das Protokoll und die Verschlüsselungscodes im SSL-Socket festlegen (sslSocket.setEnabledProtocols (..)

Sie können auch einen SSLContext mit dem erforderlichen Protokoll aktivieren, und dieses für die von Ihnen verwendeten SSL-Komponenten verwenden. SSLContext.getInstance ("TLSvx.x"). Beachten Sie, dass standardmäßig ein Kontext mit allen weniger als TLSvx.x aktivierten Protokollen zurückgegeben wird. Wenn Sie "jdk.tls.client.protocols" konfiguriert haben, wird ein Kontext mit diesen aktivierten Protokollen zurückgegeben .

Es wäre keine gute Idee, die Protokolle im Code fest zu codieren. Häufig werden wir auf bestimmte Kunden stoßen, die eine bestimmte Version benötigen, entweder weil sie alte Server verwenden oder in einigen TLS-Versionen schwerwiegende Sicherheitsanfälligkeiten auftreten. Entweder man setzt es durch die Systemeigenschaften oder, wenn man explizit in sslsocket oder sslengine einstellt, liest man das aus einer conf-Datei.

Auch verweisen:

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

Verwandte Themen