EDIT: Entschuldigung, wenn mein ursprünglicher Beitrag schlecht formuliert war. Es führte zu einiger Verwirrung, die durch Kommentare zum ursprünglichen Beitrag dargestellt wird. Also lass es mich nochmal versuchen:
Ich habe mit einer Frage angefangen. Ich wollte ein Problem auf Android lösen, wusste aber nicht wie. Ich habe viel Zeit damit verbracht, im Internet nach Lösungen zu suchen, fand aber nirgendwo eine einzige Diskussion. Nichtsdestotrotz führte mich eine Reihe von Diskussionen, einschließlich StackOverflow-Threads, zu einer Technik, die vielversprechend aussah. Ich habe das Problem gelöst. Aber die Lösung war ein wenig beteiligt. Also habe ich mich entschieden, die Frage hier zu stellen und a) es muss eine bessere Lösung geben, und hoffentlich wird jemand die Antwort hier wissen und posten; oder b) vielleicht ist das eine gute Lösung, und da ich nirgends sonst im Internet eine Diskussion über die Angelegenheit fand, wäre meine Lösung des Problems vielleicht nützlich für andere, die versuchen, dasselbe zu tun. So oder so, das Ergebnis wäre ein neuer Beitrag zu StackOverflow: eine Frage, die anderswo nicht beantwortet wird, mit der richtigen Antwort auf die eine oder andere Weise. Tatsächlich hat mich StackOverflow sogar dazu eingeladen, meine eigene Frage zu beantworten, indem ich mein Wissen teilte, als ich es ursprünglich gepostet habe. Das war in der Tat Teil meiner Motivation. Auch die Fakten dieser Angelegenheit sind nirgends gesammelt, die ich gefunden habe.
Also:
Q. Wie kann ich bei Verwendung des AndroidHttpClient für die Ausführung von REST-Anforderungen über HTTPS angeben, welche SSL-Protokolle und -Chipherien verwendet werden sollen?
Das ist wichtig. Der Punkt ist gut, dass es viel gibt, was auf dem Server getan werden kann, aber es gibt Grenzen. Derselbe Server muss Browser, einschließlich der alten, sowie anderer Clients bedienen. Das bedeutet, dass der Server eine breite Palette von Protokollen und Verschlüsselungen unterstützen muss. Selbst wenn Sie innerhalb von Android viele verschiedene Versionen unterstützen müssen, müssen Sie eine Reihe verschiedener Protokolle und Verschlüsselungen unterstützen.
Wichtiger ist, dass OpenSSL standardmäßig die Verschlüsselungseinstellung des Clients, nicht , während des SSL-Handshakes berücksichtigt. Sehen Sie sich zum Beispiel posten an, das besagt, dass Sie dieses Verhalten im Client überschreiben können, indem Sie SSL_OP_CIPHER_SERVER_PREFERENCE festlegen. Es ist nicht ganz klar, ob diese Option auch auf einem SSLSocket in Java gesetzt werden kann. Auch wenn dies möglich ist, können Sie die Verschlüsselungsliste selbst festlegen oder Ihrem Client mitteilen, dass er die Serverliste berücksichtigen soll. Andernfalls erhalten Sie die Android-Standardeinstellung, unabhängig davon, für welche Version Sie die Version verwenden (nicht die Version, für die Sie eine Verknüpfung herstellen).
Wenn Sie die Standardwerte verwenden, wird die vom Client an den Server von einem Jellybean 4.2 + -Client gesendete Präferenzliste hier , beginnend bei Zeile 504. Die Standardliste von Protokollen beginnt bei Zeile 620. Obwohl Jellybean 4.2 + enthält Unterstützung für OpenSSL 1.0.1, insbesondere TLSv1.1 und TLSv1.2, diese Protokolle sind standardmäßig nicht aktiviert. Wenn Sie etwas nicht tun, was ich getan habe, können Sie die TLSv1.2-Unterstützung nicht nutzen, obwohl die Unterstützung für TLSv1.2 in den neuesten Versionen von Android angekündigt wird. Und die Details variieren ziemlich, wenn Sie frühere Android-Versionen verwenden. Zumindest möchten Sie vielleicht die Standardeinstellungen aller unterstützten Versionen genau betrachten und sehen, was Ihr Client tatsächlich macht. Sie könnten überrascht sein.
Es gibt viel mehr, was Sie über die Unterstützung für verschiedene Protokolle und Verschlüsselungen sagen können. Der Punkt ist, dass es manchmal notwendig sein kann, diese Einstellungen in einem Client zu ändern.
A. Verwenden Sie eine benutzerdefinierte SSLSocketFactory
Das hat gut für mich funktioniert, und am Ende war es nicht sehr viel Code. Aber es war ein wenig dornig für eine Reihe von Gründen:
Die wichtigsten Punkte:
%Vor%Dann:
%Vor%Unter Android 3.0 (Honeycomb / SDK 11) sind die unterstützten Verschlüsselungsoptionen begrenzter und es gibt weniger Motivation, die Standardeinstellungen zu überschreiben. Auf FROYO / SDK 8, meine SecureSocketFactory explodiert aus irgendeinem Grund, und die Jury ist auf 10 hinaus. Aber es scheint für 11 aufwärts funktionieren gut.
Die vollständige Lösung befindet sich in einem öffentlichen GitHub Repo .
Eine andere Lösung könnte darin bestehen, eine HttpsUrlConnection zu verwenden, die die Verwendung einer benutzerdefinierten Socket-Factory vereinfacht, aber ich nehme an, dass Sie wahrscheinlich noch mehr von der Bequemlichkeit des High-Level-HTTP-Clients verlieren werden. Ich habe keine Erfahrung mit HttpsUrlConnection.
Wie kann ich bei der Verwendung von AndroidHttpClient für REST-Anforderungen über HTTPS angeben, welche SSL-Protokolle und -Chips verwendet werden sollen?
Ich glaube nicht, dass du es mit AndroidHttpClient
schaffen kannst. Alles, was ich getan habe, um den Kanal zu härten (wie Chiffre-Listen, Zertifikats-Pinning und Public-Key-Pinning), erforderte irgendwo eine benutzerdefinierte Klasse, egal ob es SSLSocketFactory
oder X509TrustManager
war. Das ist Java und das ist Android. Siehe Wie überschreiben die Cipherlist, die von Android an den Server gesendet wird, wenn HttpsURLConnection verwendet wird? .