背景
有些时候,为了做内部测试,服务器上得配置自签名证书,这样安卓客户端需要通过自签名证书去访问.
解决方案
- 增加工具类HttpsUtil
class HttpsUtil {
class SSLParams {
lateinit var sSLSocketFactory: SSLSocketFactory
lateinit var trustManager: X509TrustManager
}
private class UnSafeTrustManager : X509TrustManager {
@SuppressLint("TrustAllX509TrustManager")
@Throws(CertificateException::class)
override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {
}
@SuppressLint("TrustAllX509TrustManager")
@Throws(CertificateException::class)
override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {
}
override fun getAcceptedIssuers(): Array<X509Certificate> {
return arrayOf()
}
}
private class MyTrustManager @Throws(NoSuchAlgorithmException::class, KeyStoreException::class)
constructor(private val localTrustManager: X509TrustManager) : X509TrustManager {
private val defaultTrustManager: X509TrustManager?
init {
val var4 = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
var4.init(null as KeyStore?)
defaultTrustManager = chooseTrustManager(var4.trustManagers)
}
@SuppressLint("TrustAllX509TrustManager")
@Throws(CertificateException::class)
override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {
}
@Throws(CertificateException::class)
override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {
try {
defaultTrustManager!!.checkServerTrusted(chain, authType)
} catch (ce: CertificateException) {
localTrustManager.checkServerTrusted(chain, authType)
}
}
override fun getAcceptedIssuers(): Array<X509Certificate> {
return arrayOf()
}
}
companion object {
fun getSslSocketFactory(certificates: Array<InputStream>, bksFile: InputStream?, password: String?): SSLParams {
val sslParams = SSLParams()
try {
val trustManagers = prepareTrustManager(*certificates)
val keyManagers = prepareKeyManager(bksFile, password)
val sslContext = SSLContext.getInstance("TLS")
var trustManager: X509TrustManager = UnSafeTrustManager()
trustManagers?.let { arrayOfTrustManagers ->
val x509TrustManager = chooseTrustManager(arrayOfTrustManagers)
x509TrustManager?.let { trustManager = MyTrustManager(it) }
}
sslContext.init(keyManagers, arrayOf<TrustManager>(trustManager), null)
sslParams.sSLSocketFactory = sslContext.socketFactory
sslParams.trustManager = trustManager
return sslParams
} catch (e: Exception) {
throw AssertionError(e)
}
}
private fun prepareTrustManager(vararg certificates: InputStream): Array<TrustManager>? {
if (certificates.isEmpty()) return null
try {
val certificateFactory = CertificateFactory.getInstance("X.509")
val keyStore = KeyStore.getInstance(KeyStore.getDefaultType())
keyStore.load(null)
for ((index, certificate) in certificates.withIndex()) {
val certificateAlias = Integer.toString(index)
keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate))
try {
certificate.close()
} catch (e: IOException) {
}
}
val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
trustManagerFactory.init(keyStore)
return trustManagerFactory.trustManagers
} catch (e: Exception) {
e.printStackTrace()
}
return null
}
private fun prepareKeyManager(bksFile: InputStream?, password: String?): Array<KeyManager>? {
try {
if (bksFile == null || password == null) return null
val clientKeyStore = KeyStore.getInstance("BKS")
clientKeyStore.load(bksFile, password.toCharArray())
val keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
keyManagerFactory.init(clientKeyStore, password.toCharArray())
return keyManagerFactory.keyManagers
} catch (e: java.lang.Exception) {
e.printStackTrace()
}
return null
}
private fun chooseTrustManager(trustManagers: Array<TrustManager>): X509TrustManager? {
for (trustManager in trustManagers) {
if (trustManager is X509TrustManager) {
return trustManager
}
}
return null
}
}
}
- 生成okHttpClient时设置sslSocketFactory
fun provideOkHttpClient(): OkHttpClient {
val sslParams = HttpsUtil.getSslSocketFactory(arrayOf(App.context.resources.openRawResource(R.raw.https_keystore)), null, null)
return OkHttpClient.Builder()
.sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)
.build()
}
附录
https工具类来自鸿洋
安卓开发技术分享: https://www.jianshu.com/p/442339952f26
点击关注专辑,查看最新技术分享
更多技术总结好文,请关注:「程序园中猿」
网友评论