我在与以下4个设备连接的服务器时遇到问题:
java.security.cert.CertPathValidatorException:的信任锚 找不到认证路径。 在com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:410) 在okhttp3.internal.connection.RealConnection.connectTls(SourceFile:319) 在okhttp3.internal.connection.RealConnection。EstablishmentProtocol(SourceFile:283) 在okhttp3.internal.connection.RealConnection.connect(SourceFile:168) 在okhttp3.internal.connection.StreamAllocation.findConnection(SourceFile:257) 在okhttp3.internal.connection.StreamAllocation.findHealthyConnection(SourceFile:135) 在okhttp3.internal.connection.StreamAllocation.newStream(SourceFile:114) 在okhttp3.internal.connection.ConnectInterceptor.intercept(SourceFile:42) 在okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:147) 在okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:121) 在okhttp3.internal.cache.CacheInterceptor.intercept(SourceFile:93) 在okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:147) 在okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:121) 在okhttp3.internal.http.BridgeInterceptor.intercept(SourceFile:93) 在okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:147) 在okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(SourceFile:126) 在okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:147) 在okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:121) 在okhttp3.RealCall.getResponseWithInterceptorChain(SourceFile:254) 在okhttp3.RealCall.execute(SourceFile:92)
服务器证书来自Cloudflare,我使用https://www.digicert.com/help/之类的几种工具进行了检查,看来还可以。
但是由于某些原因,我不知道它在Android 4版本中开始失败。
尝试了信任所有证书[LINK]的解决方案,并且可以正常工作,但这显然存在一些安全问题,例如将您的应用程序暴露给“中间人”攻击
final TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
}
};
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
okHttpBuilder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
如何以默认行为实现TrustManager,但仅将服务器证书列入白名单。
谢谢
编辑:遵循OkHttp@CustomTrust上的示例(感谢CommonsWare)
使用了命令:
openssl s_client -showcerts -servername www.serverdomain.com -connect www.serverdomain.com:443
在证书链上,我给了我两个格式如下的证书:
-----BEGIN CERTIFICATE-----
....
-----END CERTIFICATE-----
将示例中的URL和证书替换为获得的URL和证书,但是仍然无法正常工作,有什么想法吗?
答案 0 :(得分:0)
您需要将您的证书存储到原始文件夹中,然后:
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream instream = context.getResources().openRawResource(R.raw.gtux_cert);
Certificate ca;
try {
ca = cf.generateCertificate(instream);
} finally {
caInput.close();
}
KeyStore kStore = KeyStore.getInstance(KeyStore.getDefaultType());
kStore.load(null, null);
kStore.setCertificateEntry("ca", ca);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm(););
tmf.init(kStore);
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
okHttpClient.setSslSocketFactory(context.getSocketFactory());
更多信息在这里:Security SSL