2013-08-14 13 views
5

Wir schreiben eine App, die mit einigen Servern über HTTPS kommunizieren muss. Es muss mit AWS kommunizieren (unter Verwendung der AWS-Bibliotheken) und auch mit einigen unserer internen Dienste, die TLS 1.2 verwenden.HttpClient unterstützt mehrere TLS-Protokolle

begann ich, indem Sie meinen Httpclient einen TLS 1.2 SSL-Kontext zu verwenden:

public static SchemeRegistry buildSchemeRegistry() throws Exception { 
    final SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); 
    sslContext.init(createKeyManager(), createTrustManager(), new SecureRandom()); 
    final SchemeRegistry schemeRegistry = new SchemeRegistry(); 
    schemeRegistry.register(new Scheme("https", 443, new SSLSocketFactory(sslContext))); 
    return schemeRegistry; 
} 

und Injizieren dieses SchemeRegistry in das DefaultHttpClient Objekt (über Feder), aber dadurch, dass ich Fehler von AWS bekommen und ich nehme an, so (ich kann mich irren), dass AWS nicht TLS unterstützt 1.2 (ich habe nicht diese Meldung, wenn ich nur die normalen DefaultHttpClient verwenden):

AmazonServiceException: Status Code: 403, AWS Service: AmazonSimpleDB, AWS Request ID: 5d91d65f-7158-91b6-431d-56e1c76a844c, AWS Error Code: InvalidClientTokenId, AWS Error Message: The AWS Access Key Id you provided does not exist in our records. 

wenn ich versuche, zwei HttpClients im Frühjahr definiert zu haben, eine das verwendet TLS 1.2 und eine, die die Standardeinstellung ist, bekomme ich die Foll wegen Fehler, die ich annehmen, bedeutet, dass der Frühling nicht mag Instanziieren und autowiring zwei Httpclient-Objekte:

SEVERE: Servlet /my-refsvc threw load() exception 
java.lang.NullPointerException 
at com.company.project.refsvc.base.HttpsClientFactory.<clinit>(BentoHttpsClientFactory.java:25) 
... 
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1031) 
at 
... 
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) 

Ich habe HTTPS in Java nicht verwendet viel, so könnte man solche Leute mir einen Rat geben, bitte? 1) Wie würde ich Spring bekommen, um zwei HttpClient Objekte zu erlauben und eines mit den AWS Stuff Beans zu verdrahten und das andere mit den anderen Beans für den Zugriff auf die TLS1.2 Services zu verbinden. 2) Oder ist es möglich zu ändern das eine HttpClient-Objekt, um TLS1.2 zu versuchen (über SSLContext, oder die SchemeRegistry oder etwas) und wenn das fehlschlägt, dann versuche TLS1.1 oder 1.0? 3) Wenn beide möglich sind, was wäre der "bessere" Weg, dies zu tun?

+0

Haben Sie den gleichen Fehler bei der Verwendung von 'SSLContext.getInstance ("TLSv1.1")' oder ' SSLContext.getInstance ("TLS") "? – Bruno

+0

Ja, ich bekomme dort denselben Fehler. Ich frage mich, ob es mein clientseitiges Zertifikat ist, das es vermasselt, anstatt die TLS-Version. – agentgonzo

+0

Versuchen Sie, den Standard-SSLContext nur für den Fall zu verwenden ("SSLContext sslContext = SSLContext.getDefault()", bereits initialisiert). Andernfalls sollten Sie weniger Anpassungen vornehmen: 'sslContext.init (createKeyManager(), null, null)' sollte den Standard für TM und SecureRandom verwenden. Es gibt keinen Standardwert für den Schlüsselverwalter, daher ist möglicherweise etwas in Ihrem Schlüsselverwaltungscode falsch (nur nützlich, wenn der Server ein Clientzertifikat anfordert). – Bruno

Antwort

3

TLS verfügt über einen eingebauten Mechanismus, um zu verhandeln, welche Version des Protokolls verwendet werden soll. Von RFC 5246 (Appendix E):

TLS-Versionen 1.0, 1.1 und 1.2 und SSL 3.0 sehr ähnlich ist, und Verwendung kompatibel Client Nachrichten; Daher ist die Unterstützung aller von ihnen relativ einfach. Ebenso können Server problemlos Clients versuchen, zukünftige Versionen von TLS zu verwenden, solange das Format ClientHello kompatibel bleibt und der Client die höchste auf dem Server verfügbare Protokollversion unterstützt.

A TLS 1.2-Client, der mit einem solchen älteren Servern zu verhandeln wünscht eine normale TLS 1.2 Client senden, mit {3, 3} (TLS 1.2) in ClientHello.client_version. Wenn der Server diese Version nicht unterstützt, antwortet er mit einem ServerHello, der eine ältere Versionsnummer enthält. Wenn der Kunde zustimmt, diese Version zu verwenden, wird die Verhandlung für das ausgehandelte Protokoll fortfahren.

Darüber hinaus die Versionsnummer in SSLContext.getInstance(...) nur Änderungen zu ändern, die Protokolle standardmäßig aktiviert sind. Die Einstellung der aktuellen Protokollversionen erfolgt mit SSLSocket.setEnabledProtocols(...) (siehe this question). Ich bin mir nicht sicher über den Rest der Bibliotheken, die Sie verwenden, aber es ist möglich, dass es die aktivierten Protokolle irgendwo setzt. unterscheidet sich von dem Standardverhalten

  • Was Sie in Ihrem createKeyManager() tun:

    Es gibt ein paar Möglichkeiten.Wenn der Dienst eine Client-Zertifikat-Authentifizierung verwendet, würde eine fehlerhafte Konfiguration zu einem Fehler 403 führen.

  • (Weniger wahrscheinlich, ich denke, aber schwer zu sagen, ohne Ihre createKeyManager() und createTrustManager() zu sehen). Möglicherweise ist der von Ihnen verwendete Server nicht mit TLS 1.2 und dem Versionsverhandlungsmechanismus kompatibel. Es gibt diesen Kommentar in sun.security.ssl.SSLContextImpl:

    SSL/TLS-Protokolle geben die Vorwärtskompatibilität und Version Roll-Back-Angriff Umzäunungen, jedoch eine Reihe von SSL/TLS-Server Anbieter nicht diese Aspekte richtig umgesetzt haben, und einige Aktuell SSL/TLS-Server verweigern möglicherweise die Kommunikation mit einem Client mit TLS 1.1 oder höher.

+0

Wir verwenden die Clientzertifikatauthentifizierung, aber ich weiß nicht, ob die Authentifizierung mit AWS-Servern mit einem Clientzertifikat, wenn sie nicht erwartet werden, Fehler verursacht oder nicht. AWS verwendet zur Authentifizierung HMAC-Signaturen, aber mehr weiß ich nicht. createKeyManager und createTrustManager laden einfach eine .jks-Datei und geben die Objekte zurück (kann in diesem Kommentar keinen Code schreiben) – agentgonzo

+0

@agentgonzo, Sie können Ihre Frage bearbeiten, wenn Sie mehr Code posten möchten. Versuchen Sie (standardmäßig), andere Einstellungen für den Keystore (die Eigenschaften javax.net.ssl. *) Zu verwenden? Was passiert, wenn Sie andere Kontexte erhalten (TLS und TLSv1.1)? – Bruno

Verwandte Themen