[英]okHTTP3 returns SSLHandshakeException: Handshake failed
該函數預計將遍歷一個目錄並將從 android API 28 模擬器找到的每個圖像發布到 Flask 后端服務器,兩者都在本地運行(來自模擬器的 API 調用: https://10.0.2.2:5000/upload
://10.0.2.2:5000/ https://10.0.2.2:5000/upload
)。
android logcat:
2020-03-18 15:51:29.417 8687-8940/com.screenomics E/MainActivity: Request{method=POST, url=https://10.0.2.2:5000/upload, tags={}}
2020-03-18 15:51:29.446 8687-8940/com.screenomics W/System.err: javax.net.ssl.SSLHandshakeException: Handshake failed
2020-03-18 15:51:29.446 8687-8940/com.screenomics W/System.err: at com.android.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(ConscryptFileDescriptorSocket.java:286)
2020-03-18 15:51:29.446 8687-8940/com.screenomics W/System.err: at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:320)
2020-03-18 15:51:29.446 8687-8940/com.screenomics W/System.err: at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:284)
2020-03-18 15:51:29.447 8687-8940/com.screenomics W/System.err: at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:169)
2020-03-18 15:51:29.447 8687-8940/com.screenomics W/System.err: at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:257)
2020-03-18 15:51:29.447 8687-8940/com.screenomics W/System.err: at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135)
2020-03-18 15:51:29.447 8687-8940/com.screenomics W/System.err: at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114)
2020-03-18 15:51:29.447 8687-8940/com.screenomics W/System.err: at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
2020-03-18 15:51:29.448 8687-8940/com.screenomics W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
2020-03-18 15:51:29.448 8687-8940/com.screenomics W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
2020-03-18 15:51:29.448 8687-8940/com.screenomics W/System.err: at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:94)
2020-03-18 15:51:29.448 8687-8940/com.screenomics W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
2020-03-18 15:51:29.448 8687-8940/com.screenomics W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
2020-03-18 15:51:29.449 8687-8940/com.screenomics W/System.err: at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
2020-03-18 15:51:29.450 8687-8940/com.screenomics W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
2020-03-18 15:51:29.450 8687-8940/com.screenomics W/System.err: at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:125)
2020-03-18 15:51:29.450 8687-8940/com.screenomics W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
2020-03-18 15:51:29.451 8687-8940/com.screenomics W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
2020-03-18 15:51:29.451 8687-8940/com.screenomics W/System.err: at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:264)
2020-03-18 15:51:29.451 8687-8940/com.screenomics W/System.err: at okhttp3.RealCall.execute(RealCall.java:93)
燒瓶控制台:
127.0.0.1 - - [18/Mar/2020 15:51:30] code 400, message Bad request version ('À')
127.0.0.1 - - [18/Mar/2020 15:51:30] " bñ³m¸È6ÁÝw^ëñÓëzߨX<.öúHÀ+Ì©À À
" HTTPStatus.BAD_REQUEST -
上傳功能
private class UploadImage2 extends AsyncTask<Void, Void, Void> {
private final MediaType PNG = MediaType.parse("image/*");
private ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.COMPATIBLE_TLS)
.tlsVersions(TlsVersion.TLS_1_2, TlsVersion.TLS_1_1, TlsVersion.TLS_1_0)
.cipherSuites(
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA)
.build();
private OkHttpClient.Builder client = new OkHttpClient.Builder()
.connectionSpecs(Collections.singletonList(spec));
private String dirpath;
private String post(File file) {
RequestBody body = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", file.getName(),
RequestBody.create(PNG, file))
.build();
Request request = new Request.Builder()
.header("Content-Type", "multipart/form-data")
.url(SERVER_ADDRESS)
.post(body)
.build();
try {
Log.e(TAG, request.toString());
Response response = client.build().newCall(request).execute();
Log.e(TAG, response.toString());
return response.body().toString();
} catch (Exception e) {
e.printStackTrace();
return e.toString();
}
}
UploadImage2(String dirpath) {
this.dirpath = dirpath;
}
@Override
protected void onPreExecute() {}
@Override
protected Void doInBackground(Void... params) {
File dir = new File(dirpath);
if (dir.exists()) {
File[] files = dir.listFiles();
if (files != null) {
for (File file : files) {
try {
String response = post(file);
Toast.makeText(getApplicationContext(), "Upload successful: " + response, Toast.LENGTH_SHORT).show();
Log.e(TAG, response);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return null;
}
Log.e(TAG, "directory not found");
return null; }
}
錯誤發生在這一行Response response = client.build().newCall(request).execute();
請幫忙! 謝謝!
這是廣泛用作解決方法的不安全 OkHttpClient。
不要在生產中使用它,它僅用於開發目的。
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import okhttp3.OkHttpClient;
public class Http {
private final static String SSL = "SSL";
private static OkHttpClient InsecureHttpClient;
public static OkHttpClient client () {
if (InsecureHttpClient == null) {
try {
InsecureHttpClient = insecureOkHttpClient ();
} catch (Exception e) {
e.printStackTrace ();
}
}
return InsecureHttpClient;
}
private static OkHttpClient insecureOkHttpClient () throws Exception {
TrustManager [] trustAllCerts = new TrustManager [] { trustManager () };
SSLContext sslContext = SSLContext.getInstance (SSL);
sslContext.init (null, trustAllCerts, new SecureRandom ());
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory ();
OkHttpClient.Builder builder = new OkHttpClient.Builder ();
builder.sslSocketFactory (sslSocketFactory, (X509TrustManager)trustAllCerts [0]);
builder.hostnameVerifier (hostnameVerifier ());
return builder.build ();
}
private static TrustManager trustManager () {
return new X509TrustManager () {
@Override
public void checkClientTrusted (X509Certificate [] chain, String authType) throws CertificateException { }
@Override
public void checkServerTrusted (X509Certificate[] chain, String authType) throws CertificateException { }
@Override
public X509Certificate [] getAcceptedIssuers () {
return new X509Certificate [] { };
}
};
}
private static HostnameVerifier hostnameVerifier () {
return new HostnameVerifier () {
@Override
public boolean verify (String hostname, SSLSession session) {
return true;
}
};
}
}
然后,您顯然可以像下面的測試代碼一樣使用上面的客戶端:(順便說一下,它適用於您的 URL)
final Request request = new Request.Builder ()
.url ("your URL")
.get ()
.addHeader ("Accept", "text/html")
.build ();
final OkHttpClient httpClient = Http.client ();
val clientCertificates = HandshakeCertificates.Builder()
.addPlatformTrustedCertificates()
.addInsecureHost("192.168.0.8")
.build()
val client = OkHttpClient.Builder()
.sslSocketFactory(clientCertificates.sslSocketFactory(), clientCertificates.trustManager)
.build()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.