例外分析
最近測驗端反饋,商品詳情里某些圖片無法展現,后來跟蹤查看了一下,發現了如下例外資訊,大概類似: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證書例外的參考,總結結束,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/229230.html
標籤:其他
上一篇:微信支付
