Android7.0 HTTPs 抓包问题
很多小伙伴,遇到在Android7.0 开发APP遇到无法抓包的问题,如果是配置了Network security configuration,可以加一行代码就可以解决
在Android7.0及以上的系统中,每个应用可以定义自己的可信CA集集。
默认情况下,应用只会信任系统预装的CA证书,而不会信任用户安装的CA证书。
而回想我们抓包的过程,无论是fiddler还是Charles,想抓https,都必须手机安装对应的证书,通过fiddler/Charles安装的证书恰恰正属于用户安装的CA证书,因此会被视作不安全的证书。
解决办法有两种:
1、配置network-security-config.xml 信任用户安装的证书
所以需要在network-security-config.xml 设置信任用户安装的证书
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="false">
</base-config>
<debug-overrides>
<trust-anchors>
<certificates src="system" overridePins="true" />
//主要是这行代码
<certificates src="user" overridePins="true" />
</trust-anchors>
</debug-overrides>
</network-security-config>
更多使用,查看Network security configuration
2、 自定义https 请求的证书
下面给出OkHttp 自定义证书的工具类
工具类
下面是工具类,只需要传入OkHttpClient.Builder对象,在使用中传入this 和自定义证书的路径(assets 资源下面的路径)
/**
* @Author: xuexuan: 2019年5月24日19:49:10
* @Description:设置okhttp 自定义证书
*/
fun OkHttpClient.Builder.sslSocketFactory(builder: OkHttpClient.Builder, path: String): OkHttpClient.Builder {
val sslUtil: SSLUtil = SSLUtil()
sslUtil.addCertificate(path, context)
builder.sslSocketFactory(sslUtil.getSSLSocketFactory(), sslUtil.mX509TrustManager)
return builder
}
class SSLUtil {
val mX509TrustManager = getTrustManager()
// 证书数据
private var CERTIFICATES_DATA = ArrayList<ByteArray?>()
/**
* 添加https证书
*
* @param inputStream
*/
@Synchronized
fun addCertificate(path: String, context: Context) {
val inputStream = context.assets.open(path)
try {
var len = 0// 数据总长度
val data = ArrayList<ByteArray>()
var ava = inputStream.available() // 数据当次可读长度
while (ava > 0) {
val buffer = ByteArray(ava)
inputStream.read(buffer)
data.add(buffer)
len += ava
ava = inputStream.available()
}
val buff = ByteArray(len)
var dstPos = 0
for (bytes in data) {
val length = bytes.size
System.arraycopy(bytes, 0, buff, dstPos, length)
dstPos += length
}
CERTIFICATES_DATA.add(buff)
} catch (e: IOException) {
e.printStackTrace()
}
}
/**
* 获取sslSocketFactory() 中需要的参数 X509TrustManager
*/
private fun getTrustManager(): X509TrustManager {
val trustManagerFactory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(getKeyStore())
val trustManagers = trustManagerFactory.trustManagers;
if (trustManagers.size != 1 || trustManagers[0] !is X509TrustManager) {
throw IllegalStateException("Unexpected default trust managers:"
+ Arrays.toString(trustManagers))
}
return trustManagers[0] as X509TrustManager
}
/**
* 获取sslSocketFactory() 中需要的参数 SSLSocketFactory
*/
fun getSSLSocketFactory(): SSLSocketFactory {
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, arrayOf(mX509TrustManager), null)
return sslContext.socketFactory
}
private fun getKeyStore(): KeyStore {
// 添加证书
val certificates = ArrayList<InputStream>()
// 将字节数组转为输入流数组
if (CERTIFICATES_DATA.isNotEmpty()) {
for (bytes in CERTIFICATES_DATA) {
certificates.add(ByteArrayInputStream(bytes))
}
}
val certificateFactory = CertificateFactory.getInstance("X.509")
val keyStore = KeyStore.getInstance(KeyStore.getDefaultType())
keyStore.load(null)
try {
var i = 0
val size = certificates.size
while (i < size) {
val certificate = certificates[i]
val certificateAlias = Integer.toString(i++)
keyStore.setCertificateEntry(certificateAlias, certificateFactory
.generateCertificate(certificate))
certificate?.close()
}
} catch (e: IOException) {
e.printStackTrace()
}
return keyStore
}
}
使用示例
Retrofit.Builder()
.client(OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
//这里使用的是kotlin的扩展函数,传入this,和assets 路径下的证书路径即可
.sslSocketFactory(this,"cers/FiddlerRoot.cer")
.build())
.baseUrl(BuildConfig.API_HOST)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(OwnerService::class.java)
请点赞、收藏,感谢大家的支持