Ich arbeite an einer Anwendung, die Lebensmittelbestellungen verarbeitet, und wir senden die Anfragen über HttpsURLConnection an eine PHS-Funktion, die ssl-zertifiziert wurde. Das Problem, das ich habe, ist, dass es den Handschlag manchmal ablehnt und andere nicht. Ich fragte mich, ob mir jemand erklären könnte, warum es es einmal und nicht ein anderes Mal ablehnen würde.

javax.net.ssl.SSLProtocolException: SSL-Handshake abgebrochen: ssl = 0x56cbe008: Fehler in der SSL-Bibliothek, normalerweise ein Protokollfehler 0x52eb6d74: 0x00000000) javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL-Handshake abgebrochen: ssl = 0x56cbe008: Fehler in der SSL-Bibliothek, normalerweise ein Protokollfehler (external / openssl / ssl / s23_clnt.c: 744 0x52eb6d74: 0x00000000)

url = new URL(request.endpointUri);

Log.d(LOG_TAG, "Opening connection to " + request.endpointUri);
conn = (HttpsURLConnection)url.openConnection();

//setup the connection
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("charset", "UTF-8");
conn.setDoInput(true);
conn.setDoOutput(true);

//setup the parameters
Uri.Builder params = new Uri.Builder();
String paramString;

params.appendQueryParameter("cctoken", request.token.getId());
params.appendQueryParameter("amt", Integer.toString(request.order.amount));
params.appendQueryParameter("email", request.order.customerEmail);
params.appendQueryParameter("order", request.order.details);

paramString = params.build().getEncodedQuery();
conn.setFixedLengthStreamingMode(paramString.getBytes("UTF-8").length);

Log.d(LOG_TAG, "Compiled query into: " + paramString);

//write the POST request params
OutputStream os = conn.getOutputStream();
BufferedWriter streamWriter = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
streamWriter.write(paramString);
streamWriter.flush();
streamWriter.close();
os.close();

//read the response
int responseCode = conn.getResponseCode();
InputStream is;

Die für den Fehler angegebene Zeile ist, wenn versucht wird, die Ausgabe zu erfassen.

OutputStream os = conn.getOutputStream();
3
Eidenai 4 Jän. 2016 im 21:56

3 Antworten

Beste Antwort

SSL-Handshake-Fehler, die nur manchmal auftreten, hängen häufig mit serverseitigen Problemen zusammen, sodass Ihr Code hier keine große Hilfe darstellt. Mögliche Ursachen auf der Serverseite sind mehrere Server mit unterschiedlicher Konfiguration (einige funktionieren, andere nicht), Zeitüberschreitungen, die durch zu hohe Auslastung verursacht werden können, Serverabstürze. Möglicherweise ist auch eine fehlerhafte Middleware (Firewalls) beteiligt. Wenn die Verbindung von Anfang an unzuverlässig ist, wirkt sich dies auch auf den SSL-Handshake aus.

Schauen Sie sich also nicht zu viel Ihren Code an, sondern den Server und das Netzwerk. Versuchen Sie im Zweifelsfall einen anderen Client, und wenn dieser ein stabileres Verhalten zeigt, untersuchen Sie die Unterschiede in der Verbindung und im SSL-Handshake (d. H. Paketerfassung).

4
Steffen Ullrich 4 Jän. 2016 im 19:22

Dieses Problem kann auf ein selbstsigniertes Zertifikat des Servers zurückzuführen sein, an den Sie eine Anfrage senden. Sie müssen Folgendes tun: `// CAs aus einem InputStream laden // (kann aus einer Ressource oder ByteArrayInputStream stammen oder ...)

CertificateFactory cf = CertificateFactory.getInstance("X.509");
// From https://www.washington.edu/itconnect/security/ca/load-der.crt

InputStream caInput = new BufferedInputStream(new FileInputStream("load-   der.crt"));
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}

// Erstellen Sie einen KeyStore mit unseren vertrauenswürdigen Zertifizierungsstellen

String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);

// Erstellen Sie einen TrustManager, der den Zertifizierungsstellen in unserem KeyStore vertraut

String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);

// Erstellen Sie einen SSLContext, der unseren TrustManager verwendet

SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);

// Weisen Sie die URLConnection an, eine SocketFactory aus unserem SSLContext zu verwenden

URL url = new URL("https://certs.cac.washington.edu/CAtest/");
HttpsURLConnection urlConnection =
(HttpsURLConnection)url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
InputStream in = urlConnection.getInputStream();
copyInputStreamToOutputStream(in, System.out);`

Fand es hier

1
Krishna 4 Jän. 2016 im 19:48

Verwandtes Problem: Client und Server unterstützen kein gemeinsames Verschlüsselungsprotokoll

Wenn die Fehlermeldung etwas sagt wie:

error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version (external/openssl/ssl/s23_clnt.c:741 0x8d92d990:0x00000000)

(Beachten Sie, dass nach 'GET_SERVER_HELLO' 'tlsv1 ' steht und nicht 'sslv3' .) Dies ist ein schwacher Hinweis darauf, dass das Problem möglicherweise bei der benötigten Verschlüsselungsversion liegt. Wenn der Client alt ist, unterstützt er möglicherweise nur sslv2 oder sslv3. Ein aktueller Server unterstützt möglicherweise TLS1.2 und nicht die älteren (möglicherweise veralteten SSL-Versionen). Das Gegenteil kann auch der Fall sein, wobei der Server nur den alten und der Client nur den neuen unterstützt.

Ich bin auf dieses Problem mit einem alten Android Jelly Bean-Client gestoßen, der TLS1.2 für HttpsUrlConnection standardmäßig nicht unterstützt. Durch Erstellen einer TLSSocketFactory und eines X509TrustManager und Aufrufen von setSSLSocketFactory () konnte ich die alte Version von Android dazu bringen, TLS1.2 zu verwenden, was den Server glücklich machte. Navneet Krishna schrieb eine gute Beschreibung, wie dies zu tun ist in: [https://medium.com/@krisnavneet/how-to-solve-sslhandshakeexception-in-android-ssl23-get-server-hello-tlsv1-alert-protocol -13b457c724ef]

0
Ribo 2 Juli 2020 im 00:56