Glide加载https 图片异常总结javax.net.ssl.SSLHandshakeException

1 篇文章 0 订阅
1 篇文章 0 订阅

异常分析

最近测试端反馈,商品详情里某些图片无法展现,后来跟踪查看了一下,发现了如下异常信息,大概类似:javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found
打眼一看就知道大概意思,这是加载https图片时 证书验证出错了,正常情况下我们平台的商品都是上传到阿里云的,没有出过这个异常信息,但是某些商品来源于 第三方平台,图片使用的地址是直接复制的第三方的链接,由于第三方证书是自签名的,所以https证书验证失败,就会出现这个异常信息,现把这个异常总结一下。

解决方案

app使用的网络框架是Retrofit2+OkHttp3,Glide版本是4.9.0,这个搭配默认android识别的开源免费的证书都可以验证通过的,不需要单独去做处理;但是如果要访问自签名证书的网络https URL,就需要去做应对策略了:

一、不考虑安全性:

这里使用kotlin注解处理器插件kapt,在app的Gradle添加配置

apply plugin: 'kotlin-kapt'

kapt 'com.github.bumptech.glide:compiler:4.9.0'
implementation "com.github.bumptech.glide:okhttp3-integration:4.9.0"

自定义GlideModule,使用一个信任所有https证书的OkHttpClient。这里需要说一下,UnsafeOkHttpClient 信任所有https证书,不检验任何hostname,我app里只赋给GIide使用,如果访问服务端资源,比如访问某接口,走的不是这一个client,但是如果不考虑安全性,也可以走同一个,根据实际应用抉择。

@GlideModule
class OkHttpAppGlideModule : AppGlideModule() {
    override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
        val client = UnsafeOkHttpClient.getUnsafeOkHttpClient()
        client?.let {
            registry.replace(GlideUrl::class.java, InputStream::class.java, OkHttpUrlLoader.Factory(client))
        }
    }
    override fun isManifestParsingEnabled(): Boolean {
        return false
    }
}
object UnsafeOkHttpClient {

    fun getUnsafeOkHttpClient(): OkHttpClient? {
        return try {
            val trustAllCerts = arrayOf<TrustManager>(
                    object : X509TrustManager {
                        override fun checkClientTrusted(
                                chain: Array<out X509Certificate>?,
                                authType: String?
                        ) {
                        }

                        override fun checkServerTrusted(
                                chain: Array<out X509Certificate>?,
                                authType: String?
                        ) {
                        }

                        override fun getAcceptedIssuers(): Array<X509Certificate> {
                            return arrayOf()
                        }
                    }
            )
            val sslContext = SSLContext.getInstance("SSL")
            sslContext.init(null, trustAllCerts, SecureRandom())
            val sslSocketFactory = sslContext.socketFactory
            val builder = OkHttpClient.Builder()
            builder.sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
            builder.hostnameVerifier(HostnameVerifier { _, _ -> true })
            builder.connectTimeout(10, TimeUnit.SECONDS)
            builder.readTimeout(20, TimeUnit.SECONDS)
            builder.build()
        } catch (e: Exception) {
            throw RuntimeException(e)
        }
    }
}

二、考虑安全性问题:

如果考虑安全性问题,就需要添加自签名的证书信息,大致代码如下:

private fun getKeyStore(fileName: String): KeyStore? {
        var keyStore: KeyStore? = null
        var caInput: InputStream? = null
        try {
            val assetManager: AssetManager = BaseApplication.instance().assets
            val cf: CertificateFactory = CertificateFactory.getInstance("X.509")
            caInput = assetManager.open(fileName)
            val ca: Certificate = cf.generateCertificate(caInput)
            val keyStoreType: String = KeyStore.getDefaultType()
            keyStore = KeyStore.getInstance(keyStoreType)
            keyStore.load(null, null)
            keyStore.setCertificateEntry("ca", ca)
        } catch (e: Exception) {
            LogUtils.e("Error during getting keystore")
            e.printStackTrace()
        } finally {
            caInput?.close()
        }
        return keyStore
    }
private fun loadCertificateFile(fileName: String,mBuilder: OkHttpClient.Builder){
	  try {
	      var keyStore: KeyStore? = getKeyStore(fileName)
	      keyStore?.let {
	          val sslContext: SSLContext = SSLContext.getInstance("SSL")
	          val trustManagerFactory: TrustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
	          trustManagerFactory.init(it)
	          sslContext.init(null, trustManagerFactory.trustManagers, SecureRandom())
	          //具体Builder,Client 根据自己需求设置
	          mBuilder.sslSocketFactory(sslContext.socketFactory,trustManagerFactory.trustManagers[0] as X509TrustManager )
	          mHttpClient = mBuilder.build()  // 此client赋给UnsafeOkHttpClient的getxxOkHttpClient方法,使Glide使用此client去加载图片即可
	      }
	  } catch (e: Exception) {
	      LogUtils.e("Error during creating SslContext for certificate from assets")
	      e.printStackTrace()
	  }
}

以上就是针对Glide加载服务端自签名证书异常的大致解决方案,也可以作为访问自签名Https证书异常的参考,总结结束。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JavPer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值