【发布时间】:2019-06-18 06:51:37
【问题描述】:
我在使用 android 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.establishProtocol(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 和证书替换为获得的,但仍然无法正常工作,有什么想法吗?
【问题讨论】:
-
感谢@CommonsWare,请检查编辑
标签: java android ssl https trustmanager