gpt4 book ai didi

Android pre-lollipop 设备给出错误 "SSL handshake aborted: ssl=0x618d9c18: I/O error during system call, Connection reset by peer"

转载 作者:可可西里 更新时间:2023-11-01 18:55:21 30 4
gpt4 key购买 nike

我遇到了这个奇怪的问题,改造不断地抛出我

"SSL handshake aborted: ssl=0x618d9c18: I/O error during system call, Connection reset by peer"

在 kitkat 中,而相同的代码在 Lollipop 设备中运行良好。我正在使用如下所示的 OkHttpClient 客户端

public OkHttpClient getUnsafeOkHttpClient() {
try {
final TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] chain,
String authType) {
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] chain,
String authType) {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[0];
}
} };

int cacheSize = 10 * 1024 * 1024; // 10 MB
Cache cache = new Cache(getCacheDir(), cacheSize);
final SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, trustAllCerts,
new java.security.SecureRandom());
final SSLSocketFactory sslSocketFactory = sslContext
.getSocketFactory();
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient = okHttpClient.newBuilder()
.cache(cache)
.sslSocketFactory(sslSocketFactory)
.hostnameVerifier(org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER).build();
return okHttpClient;
} catch (Exception e) {
throw new RuntimeException(e);
}

}

我正在像这样改造使用这个客户端

Retrofit retrofit = new Retrofit.Builder()
.baseUrl(URL)
.client(getUnsafeOkHttpClient())
.addConverterFactory(GsonConverterFactory.create())
.build();

编辑:添加 getUnsafeOkHttpClient()在这里没有效果,完全不建议使用 getUnsafeOkHttpClient() 来绕过 ssl 检查。

仅供引用:问题是因为 api 端点仅支持 TLS 1.2 在 android 设备上默认禁用 16<device<20 。所以对于 16<device<20 ,创建自定义 SSLSocketFactory

最佳答案

终于找到了这个问题的解决方案,它不是一个完整的解决方案,因为它是 Jesse Wilson 提到的黑客攻击来自 okhttp, square here .正如我提到的,这是一个简单的 hack,我不得不将我的 SSLSocketFactory 变量重命名为

private SSLSocketFactory delegate;

请注意,如果您提供除委托(delegate)以外的任何名称,它会抛出错误。我在下面发布我的完整解决方案

这是我的TLSSocketFactory

public class TLSSocketFactory extends SSLSocketFactory {

private SSLSocketFactory delegate;
private TrustManager[] trustManagers;

public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {
generateTrustManagers();
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, trustManagers, null);
delegate = context.getSocketFactory();
}

private void generateTrustManagers() throws KeyStoreException, NoSuchAlgorithmException {
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();

if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers:"
+ Arrays.toString(trustManagers));
}

this.trustManagers = trustManagers;
}


@Override
public String[] getDefaultCipherSuites() {
return delegate.getDefaultCipherSuites();
}

@Override
public String[] getSupportedCipherSuites() {
return delegate.getSupportedCipherSuites();
}

@Override
public Socket createSocket() throws IOException {
return enableTLSOnSocket(delegate.createSocket());
}

@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return enableTLSOnSocket(delegate.createSocket(s, host, port, autoClose));
}

@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
return enableTLSOnSocket(delegate.createSocket(host, port));
}

@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
return enableTLSOnSocket(delegate.createSocket(host, port, localHost, localPort));
}

@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return enableTLSOnSocket(delegate.createSocket(host, port));
}

@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return enableTLSOnSocket(delegate.createSocket(address, port, localAddress, localPort));
}

private Socket enableTLSOnSocket(Socket socket) {
if(socket != null && (socket instanceof SSLSocket)) {
((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"});
}
return socket;
}

@Nullable
public X509TrustManager getTrustManager() {
return (X509TrustManager) trustManagers[0];
}

}

这就是我将它与 okhttp 和 retrofit 一起使用的方式

 OkHttpClient client=new OkHttpClient();
try {
TLSSocketFactory tlsSocketFactory=new TLSSocketFactory();
if (tlsSocketFactory.getTrustManager()!=null) {
client = new OkHttpClient.Builder()
.sslSocketFactory(tlsSocketFactory, tlsSocketFactory.getTrustManager())
.build();
}
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
}

Retrofit retrofit = new Retrofit.Builder()
.baseUrl(URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();

编辑:public Builder sslSocketFactory(SSLSocketFactory sslSocketFactory) 方法现已弃用,我们应该使用public Builder sslSocketFactory(
SSLSocketFactory sslSocketFactory, X509TrustManager trustManager)
正如我在答案中更新的那样。这是因为 X509TrustManager 是 OkHttp 需要构建一个干净的证书链的字段,它没有在弃用的方法中使用。

您也可以查看 this for more info

关于Android pre-lollipop 设备给出错误 "SSL handshake aborted: ssl=0x618d9c18: I/O error during system call, Connection reset by peer",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45984295/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com