栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > .Net

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

.Net 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

异常分析

最近测试端反馈,商品详情里某些图片无法展现,后来跟踪查看了一下,发现了如下异常信息,大概类似: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(
                    object : X509TrustManager {
                        override fun checkClientTrusted(
                                chain: Array?,
                                authType: String?
                        ) {
                        }

                        override fun checkServerTrusted(
                                chain: Array?,
                                authType: String?
                        ) {
                        }

                        override fun getAcceptedIssuers(): Array {
                            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证书异常的参考,总结结束。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/907237.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号