Android老版本应用HTTPS登录遇CertificateExpiredException问题求助
问题背景
该错误仅出现在一款2018年左右创建的Android应用中,此前一直正常运行,数月前开始出现异常。错误触发于发起HTTPS POST登录API请求时,指向同一接口的iOS版本应用运行正常。
问题现象
日志显示登录请求已成功,但受该错误影响无法进入登录后的页面;重新创建应用并配置登录组件后,日志显示可正常登录API,说明仅该特定版本应用存在问题。
错误日志
W/System.err: javax.net.ssl.SSLHandshakeException: Chain validation failed W/System.err: at com.android.org.conscrypt.SSLUtils.toSSLHandshakeException(SSLUtils.java:362) W/System.err: at com.android.org.conscrypt.ConscryptEngine.convertException(ConscryptEngine.java:1134) W/System.err: at com.android.org.conscrypt.ConscryptEngine.readPlaintextData(ConscryptEngine.java:1089) W/System.err: at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:876) W/System.err: at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:747) W/System.err: at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:712) W/System.err: at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.processDataFromSocket(ConscryptEngineSocket.java:849) W/System.err: at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.access$100(ConscryptEngineSocket.java:722) W/System.err: at com.android.org.conscrypt.ConscryptEngineSocket.doHandshake(ConscryptEngineSocket.java:238) W/System.err: at com.android.org.conscrypt.ConscryptEngineSocket.startHandshake(ConscryptEngineSocket.java:217) W/System.err: at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.kt:379) W/System.err: at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.kt:337) W/System.err: at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:209) W/System.err: at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226) W/System.err: at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106) W/System.err: at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74) W/System.err: at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255) W/System.err: at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32) W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) W/System.err: at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95) W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) W/System.err: at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83) W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) W/System.err: at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76) W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) W/System.err: at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201) W/System.err: at okhttp3.internal.connection.RealCall.execute(RealCall.kt:154) W/System.err: at retrofit2.OkHttpCall.execute(OkHttpCall.java:188) W/System.err: at retrofit2.adapter.rxjava2.CallExecuteObservable.subscribeActual(CallExecuteObservable.java:45) W/System.err: at io.reactivex.Observable.subscribe(Observable.java:12267) W/System.err: at retrofit2.adapter.rxjava2.BodyObservable.subscribeActual(BodyObservable.java:34) W/System.err: at io.reactivex.Observable.subscribe(Observable.java:12267) W/System.err: at io.reactivex.internal.operators.flowable.FlowableFromObservable.subscribeActual(FlowableFromObservable.java:29) W/System.err: at io.reactivex.Flowable.subscribe(Flowable.java:14918) W/System.err: at io.reactivex.internal.operators.flowable.FlowableOnBackpressureLatest.subscribeActual(FlowableOnBackpressureLatest.java:32) W/System.err: at io.reactivex.Flowable.subscribe(Flowable.java:14918) W/System.err: at io.reactivex.internal.operators.flowable.FlowableFlatMap.subscribeActual(FlowableFlatMap.java:53) W/System.err: at io.reactivex.Flowable.subscribe(Flowable.java:14918) W/System.err: at io.reactivex.internal.operators.flowable.FlowableMap.subscribeActual(FlowableMap.java:37) W/System.err: at io.reactivex.Flowable.subscribe(Flowable.java:14918) W/System.err: at io.reactivex.Flowable.subscribe(Flowable.java:14865) W/System.err: at io.reactivex.internal.operators.flowable.FlowableOnErrorNext$OnErrorNextSubscriber.onError(FlowableOnErrorNext.java:115) W/System.err: at io.reactivex.internal.operators.single.SingleToFlowable$SingleToFlowableObserver.onError(SingleToFlowable.java:67) W/System.err: at io.reactivex.internal.operators.single.SingleCreate$Emitter.tryOnError(SingleCreate.java:94) W/System.err: at io.reactivex.internal.operators.single.SingleCreate$Emitter.onError(SingleCreate.java:80) W/System.err: at com.parabit.parabeacon.app.demo.data_section.LocalStorage.lambda$getDeviceIdInfo$15(LocalStorage.java:236) W/System.err: at com.parabit.parabeacon.app.demo.data_section.LocalStorage$$ExternalSyntheticLambda9.subscribe(Unknown Source:2) W/System.err: at io.reactivex.internal.operators.single.SingleCreate.subscribeActual(SingleCreate.java:39) W/System.err: at io.reactivex.Single.subscribe(Single.java:3603) W/System.err: at io.reactivex.internal.operators.single.SingleToFlowable.subscribeActual(SingleToFlowable.java:37) W/System.err: at io.reactivex.Flowable.subscribe(Flowable.java:14918) W/System.err: at io.reactivex.internal.operators.flowable.FlowableOnErrorNext.subscribeActual(FlowableOnErrorNext.java:40) W/System.err: at io.reactivex.Flowable.subscribe(Flowable.java:14918) W/System.err: at io.reactivex.internal.operators.flowable.FlowableFlatMap.subscribeActual(FlowableFlatMap.java:53) W/System.err: at io.reactivex.Flowable.subscribe(Flowable.java:14918) W/System.err: at io.reactivex.Flowable.subscribe(Flowable.java:14865) W/System.err: at io.reactivex.internal.operators.flowable.FlowableFlatMap$MergeSubscriber.onNext(FlowableFlatMap.java:163) W/System.err: at io.reactivex.internal.operators.flowable.FlowableFromArray$ArraySubscription.slowPath(FlowableFromArray.java:162) W/System.err: at io.reactivex.internal.operators.flowable.FlowableFromArray$BaseArraySubscription.request(FlowableFromArray.java:90) W/System.err: at io.reactivex.internal.operators.flowable.FlowableFlatMap$MergeSubscriber.onSubscribe(FlowableFlatMap.java:117) W/System.err: at io.reactivex.internal.operators.flowable.FlowableFromArray.subscribeActual(FlowableFromArray.java:38) W/System.err: at io.reactivex.Flowable.subscribe(Flowable.java:14918) W/System.err: at io.reactivex.internal.operators.flowable.FlowableFlatMap.subscribeActual(FlowableFlatMap.java:53) W/System.err: at io.reactivex.Flowable.subscribe(Flowable.java:14918) W/System.err: at io.reactivex.Flowable.subscribe(Flowable.java:14865) W/System.err: at io.reactivex.internal.operators.flowable.FlowableSubscribeOn$SubscribeOnSubscriber.run(FlowableSubscribeOn.java:82) W/System.err: at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66) W/System.err: at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57) W/System.err: at java.util.concurrent.FutureTask.run(FutureTask.java:266) W/System.err: at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301) W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) W/System.err: at java.lang.Thread.run(Thread.java:923) W/System.err: Caused by: java.security.cert.CertificateException: Chain validation failed W/System.err: at com.android.org.conscrypt.TrustManagerImpl.verifyChain(TrustManagerImpl.java:724) W/System.err: at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:554) W/System.err: at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:575) W/System.err: at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:620) I/chatty: uid=10207(com.parabit.parabeacon.app.demo) identical 1 line W/System.err: at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:620) W/System.err: at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:510) W/System.err: at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:428) W/System.err: at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:356) W/System.err: at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94) W/System.err: at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:90) W/System.err: at com.android.org.conscrypt.ConscryptEngineSocket$2.checkServerTrusted(ConscryptEngineSocket.java:161) W/System.err: at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:250) W/System.err: at com.android.org.conscrypt.ConscryptEngine.verifyCertificateChain(ConscryptEngine.java:1644) W/System.err: at com.android.org.conscrypt.NativeCrypto.ENGINE_SSL_read_direct(Native Method) W/System.err: at com.android.org.conscrypt.NativeSsl.readDirectByteBuffer(NativeSsl.java:568) W/System.err: at com.android.org.conscrypt.ConscryptEngine.readPlaintextDataDirect(ConscryptEngine.java:1095) W/System.err: at com.android.org.conscrypt.ConscryptEngine.readPlaintextData(ConscryptEngine.java:1079) W/System.err: ... 70 more W/System.err: Caused by: java.security.cert.CertPathValidatorException: timestamp check failed W/System.err: at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:135) W/System.err: at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:222) W/System.err: at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:140) W/System.err: at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:79) W/System.err: at java.security.cert.CertPathValidator.validate(CertPathValidator.java:301) W/System.err: at com.android.org.conscrypt.TrustManagerImpl.verifyChain(TrustManagerImpl.java:720) W/System.err: ... 87 more W/System.err: Caused by: java.security.cert.CertificateExpiredException: Certificate expired at Thu Oct 20 19:59:59 EDT 2022 (compared to Wed Jan 04 17:53:35 EST 2023) //<- Here's the real issue W/System.err: at com.android.org.conscrypt.OpenSSLX509Certificate.checkValidity(OpenSSLX509Certificate.java:269) W/System.err: at sun.security.provider.certpath.BasicChecker.verifyTimestamp(BasicChecker.java:194) W/System.err: at sun.security.provider.certpath.BasicChecker.check(BasicChecker.java:144) W/System.err: at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:125) W/System.err: ... 92 more
求助说明
我已搜索一整天但未找到可行解决方案,恳请各位提供思路或解决办法,如需更多信息请告知。
补充:该Android应用基于Android Studio构建。
解决方案
从错误日志根因CertificateExpiredException可明确问题:应用信任的证书链中有证书在2022年10月20日过期,iOS应用正常是因为系统信任的根证书库已自动更新,旧Android应用对应解决办法如下:
1. 替换应用内置的过期证书
如果旧版本应用手动内置了服务器/中间证书(早年为兼容旧Android版本硬编码):
- 从服务器获取当前有效的完整证书链(含服务器证书、中间证书、根证书)
- 替换应用中内置的旧证书文件
- 重新编译打包发布应用
2. 更新网络依赖库版本
旧版OkHttp、Retrofit可能存在证书链处理缺陷,或未兼容新根证书:
- 将OkHttp升级到最新稳定版(如从旧版本升级至4.x系列)
- 同步更新Retrofit及相关适配器(如rxjava2适配器)
- 清理项目缓存后重新构建
3. 配置网络安全策略适配旧系统
Android 8.0以下系统的根证书库未包含新根证书,可通过配置解决:
- 在
res/xml/network_security_config.xml中配置信任当前服务器的证书链 - 或配置允许同时使用系统与应用内置的证书源
4. 临时排查验证(仅测试环境用)
临时禁用证书验证,确认是否为证书问题(禁止生产环境使用):
// OkHttp配置示例 OkHttpClient client = new OkHttpClient.Builder() .sslSocketFactory(new SSLSocketFactoryCompat(), new TrustAllManager()) .hostnameVerifier((hostname, session) -> true) .build(); // 辅助实现类 static class TrustAllManager implements X509TrustManager { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) {} @Override public void checkServerTrusted(X509Certificate[] chain, String authType) {} @Override public X509Certificate[] getAcceptedIssuers() {return new X509Certificate[0];} }
内容的提问来源于stack exchange,提问作者OEThe11
相关产品推荐
相关产品推荐

