2013-08-14 21 views
5

Stiamo scrivendo un'app che deve comunicare con alcuni server tramite HTTPS. Ha bisogno di comunicare con AWS (usando le librerie AWS) e anche con alcuni dei nostri servizi interni che utilizzano TLS 1.2.HttpClient che supporta più protocolli TLS

Ho iniziato cambiando il mio HttpClient utilizzare un TLS 1.2 SSLContext:

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

e l'iniezione di questa SchemeRegistry nell'oggetto DefaultHttpClient (via primavera), ma facendo che ricevo gli errori da AWS e così presumo (potrei sbagliarmi) che AWS non supporta TLS 1.2 (non ottengo questo messaggio se mi basta usare il DefaultHttpClient normale):

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. 

Se cerco di avere due HttpClients definiti in primavera, uno che usa TLS 1.2 e uno che è l'impostazione predefinita, ottengo il foll errore, che presumo a causa significa che la primavera non piace istanziare e autowiring due oggetti HttpClient:

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) 

Non ho usato HTTPS molto in Java in modo da potreste gente gentile darmi qualche consiglio per favore? 1) Come potrei ottenere Spring per consentire due oggetti HttpClient e uno per essere collegato ai bean stuff di AWS e l'altro per essere collegato agli altri bean per accedere ai servizi TLS1.2 2) Oppure è possibile cambiare l'unico oggetto HttpClient per provare TLS1.2 (tramite SSLContext, o SchemeRegistry o qualcosa del genere) e se fallisce provare TLS1.1 o 1.0? 3) Se entrambi sono possibili, quale sarebbe il modo migliore di farlo?

+0

si ottiene lo stesso errore quando si utilizza 'SSLContext.getInstance ("TLSv1.1")' o ' SSLContext.getInstance ("TLS") '? – Bruno

+0

Sì, ho lo stesso errore lì. Mi chiedo se sia il mio certificato sul lato client a rovinarlo piuttosto che la versione TLS. – agentgonzo

+0

Provare ad usare il 'SSLContext' predefinito nel caso in cui (' SSLContext sslContext = SSLContext.getDefault() ', già inizializzato). Altrimenti, prova meno personalizzazioni: 'sslContext.init (createKeyManager(), null, null)' dovrebbe usare l'impostazione predefinita per TM e SecureRandom. Non c'è un default per il keymanager, quindi potrebbe esserci ancora qualcosa di sbagliato nel codice keymanager (utile solo se il server richiede un certificato client). – Bruno

risposta

3

TLS ha un meccanismo integrato per negoziare quale versione del protocollo deve essere utilizzata. Da RFC 5246 (Appendix E):

TLS versioni 1.0, 1.1 e 1.2, e SSL 3.0 sono molto simili, e utilizzare i messaggi ClientHello compatibili; quindi, supportarli tutti è relativamente facile. Allo stesso modo, i server possono facilmente gestire i client cercando di utilizzare le versioni future di TLS purché il formato ClientHello rimanga compatibile e il client supporti la versione di protocollo più alta disponibile nel server.

Un TLS 1.2 cliente che vuole negoziare con questi vecchi server invierà un normale TLS 1.2 ClientHello, contenente {3, 3} (TLS 1.2) in ClientHello.client_version. Se il server non supporta questa versione, risponderà con un ServerHello contenente un numero di versione precedente . Se il cliente accetta di utilizzare questa versione, , la negoziazione procederà come appropriato per il protocollo negoziato .

Inoltre, cambiando il numero di versione in SSLContext.getInstance(...) solo le modifiche quali protocolli sono abilitati predefinita. L'impostazione delle versioni effettive del protocollo viene eseguita con SSLSocket.setEnabledProtocols(...) (vedere this question). Non sono sicuro del resto delle librerie che stai utilizzando, ma è possibile che imposti da qualche parte i protocolli abilitati.

Ci sono alcune possibilità:

  • Che cosa si sta facendo nel vostro createKeyManager() differisce dal comportamento predefinito.Se il servizio utilizza l'autenticazione del certificato client, una configurazione errata comporterebbe sicuramente un errore 403.

  • (Meno probabile, credo, ma difficile da dire senza vedere il tuo createKeyManager() e createTrustManager()). Forse il server che stai utilizzando non è compatibile con TLS 1.2 e il meccanismo di negoziazione della versione. C'è questo commento in sun.security.ssl.SSLContextImpl:

    protocolli SSL/TLS specificano la compatibilità in avanti e la versione di roll-back protezioni attacco, tuttavia, un certo numero di SSL/TLS del server fornitori hanno non implementano questi aspetti correttamente, e un po ' corrente I server SSL/TLS possono rifiutarsi di parlare con un client TLS 1.1 o successivo.

+0

Utilizziamo l'autenticazione del certificato client, ma non so se provare ad autenticare con i server AWS con un certificato client quando non si aspettano che uno causerà errori o meno. AWS utilizza la firma HMAC per l'autenticazione, ma più di questo non lo so. createKeyManager e createTrustManager caricano semplicemente un file .jks e restituiscono gli oggetti da quello (non è possibile inserire il codice in questo commento) – agentgonzo

+0

@agentgonzo, è possibile modificare la domanda se si desidera inviare più codice. L'applicazione (di default) tenta di utilizzare altre impostazioni per il keystore (proprietà javax.net.ssl. *)? Cosa succede se ottieni altri contesti (TLS e TLSv1.1)? – Bruno