首次启动AWS Kinesis WebRTC流时触发SSLPeerUnverifiedException异常
问题描述
我用AWS Kinesis WebRTC实现摄像头实时视频流功能,应用首次安装启动时,在创建连接阶段崩溃,抛出SSLPeerUnverifiedException异常;但重启设备或应用后就能正常运行,试了不少线上方案都没解决。
触发异常的代码行
val describeSignalingChannelResult = awsKinesisVideoClient?.describeSignalingChannel( DescribeSignalingChannelRequest() .withChannelName(channelName) )
异常信息
EXCEPTION: DefaultDispatcher-worker-1 Process: com.secure56.app, PID: 26211 com.amazonaws.AmazonClientException: Unable to execute HTTP request: Hostname kinesisvideo.ap-south-1.amazonaws.com not verified: certificate: sha1/------------------ DN: CN=kinesisvideo.ap-south-1.amazonaws.com subjectAltNames: [kinesisvideo.ap-south-1.amazonaws.com] at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:456) at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:229) at com.amazonaws.services.kinesisvideo.AWSKinesisVideoClient.invoke(AWSKinesisVideoClient.java:2077) at com.amazonaws.services.kinesisvideo.AWSKinesisVideoClient.describeSignalingChannel(AWSKinesisVideoClient.java:930) at com.android56.app.onecam.kvs.SignallingDataCreator.updateSignallingChannelInfoTask(SignallingDataCreator.kt:158) at com.android56.app.onecam.kvs.SignallingDataCreator$updateSignallingChannelInfoTask$1.invokeSuspend(Unknown Source:15) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106) at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42) at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95) at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664) Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@fb144, Dispatchers.IO] Caused by: javax.net.ssl.SSLPeerUnverifiedException: Hostname kinesisvideo.ap-south-1.amazonaws.com not verified: certificate: sha1/z60CQXD0myU9Ol4CyrQpESqcV3Y= DN: CN=kinesisvideo.ap-south-1.amazonaws.com subjectAltNames: [kinesisvideo.ap-south-1.amazonaws.com] at com.android.okhttp.internal.io.RealConnection.connectTls(RealConnection.java:1480) at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:1415) at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:1359) at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:221) at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:144) at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:106) at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:400) at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:333) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:483) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:135) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:266) at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getOutputStream(DelegatingHttpsURLConnection.java:219) at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:30) at com.google.firebase.perf.network.InstrURLConnectionBase.getOutputStream(InstrURLConnectionBase.java:165) at com.google.firebase.perf.network.InstrHttpsURLConnection.getOutputStream(InstrHttpsURLConnection.java:89) at com.amazonaws.http.UrlHttpClient.writeContentToConnection(UrlHttpClient.java:162) at com.amazonaws.http.UrlHttpClient.execute(UrlHttpClient.java:75) at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:386)
依赖配置
def aws_version = '2.68.0' implementation("com.amazonaws:aws-android-sdk-kinesisvideo:$aws_version@aar") { transitive = true } implementation("com.amazonaws:aws-android-sdk-kinesisvideo-signaling:$aws_version@aar") { transitive = true } implementation("com.amazonaws:aws-android-sdk-kinesisvideo-webrtcstorage:$aws_version@aar") { transitive = true } implementation('org.glassfish.tyrus.bundles:tyrus-standalone-client:1.20') { exclude module: 'javax.inject' } implementation 'org.awaitility:awaitility:3.0.0'
解决方案
这个问题大概率是首次启动时Android系统SSL证书缓存未加载完成,或是AWS SDK证书验证逻辑在首次初始化时存在异常,可尝试以下方案:
预加载AWS根证书
把AWS根证书打包到应用资源中,手动初始化SSL上下文时加载该证书,避免依赖系统证书缓存。在初始化AWSKinesisVideoClient前,配置自定义ClientConfiguration:val clientConfig = ClientConfiguration() val sslContext = SSLContext.getInstance("TLS") val trustManager = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()).apply { val certInputStream = context.resources.openRawResource(R.raw.amazon_root_ca) val keyStore = KeyStore.getInstance(KeyStore.getDefaultType()).apply { load(null, null) val cf = CertificateFactory.getInstance("X.509") val cert = cf.generateCertificate(certInputStream) setCertificateEntry("AmazonRootCA", cert) } init(keyStore) }.trustManagers[0] as X509TrustManager sslContext.init(null, arrayOf(trustManager), SecureRandom()) clientConfig.sslSocketFactory = sslContext.socketFactory val awsKinesisVideoClient = AWSKinesisVideoClientBuilder.standard() .withClientConfiguration(clientConfig) .withRegion(Regions.AP_SOUTH_1) .withCredentials(yourCredentialsProvider) .build()添加重试机制
针对首次启动的SSL异常添加重试逻辑,因为重启后正常说明后续尝试能通过验证:suspend fun getSignalingChannelInfo(channelName: String): DescribeSignalingChannelResult? { repeat(3) { attempt -> return try { awsKinesisVideoClient?.describeSignalingChannel( DescribeSignalingChannelRequest().withChannelName(channelName) ) } catch (e: SSLPeerUnverifiedException) { if (attempt == 2) throw e delay(1000) null } } return null }升级AWS SDK版本
当前使用的2.68.0版本较旧,后续版本可能修复了首次启动的SSL验证问题,尝试升级到较新的稳定版本。排查Firebase Performance干扰
异常栈中出现Firebase性能监控的网络拦截类,有可能是其拦截逻辑导致SSL验证异常。可临时禁用该功能,确认是否解决问题,再调整Firebase Perf配置避免拦截AWS请求。
内容的提问来源于stack exchange,提问作者anil
相关产品推荐
相关产品推荐

