最近升級(jí)了 targetSdkVersion 到 28 后發(fā)現(xiàn)在 Android 7.0 以上機(jī)型 Charles 抓取 https 包時(shí)顯示找不到證書(shū),但是 Android 6.0 機(jī)型還是可以正常抓包窍株。原因是因?yàn)閺?Android 7.0 開(kāi)始挽拔,默認(rèn)的網(wǎng)絡(luò)安全性配置修改了驹尼,具體請(qǐng)閱讀官方文檔網(wǎng)絡(luò)安全性配置杯聚。
問(wèn)題原因
Android 6.0(API 23)及更低版本應(yīng)用的默認(rèn)網(wǎng)絡(luò)安全性配置如下:
<!-- 默認(rèn)允許所有明文通信 -->
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<!-- 信任系統(tǒng)預(yù)裝 CA 證書(shū) -->
<certificates src="system" />
<!-- 信任用戶添加的 CA 證書(shū)读规,Charles 和 Fiddler 抓包工具安裝的證書(shū)屬于此類 -->
<certificates src="user" />
</trust-anchors>
</base-config>
而在 Android 7.0(API 24)到 Android 8.1(API 27)的默認(rèn)網(wǎng)絡(luò)安全性配置如下:
<!-- 默認(rèn)允許所有明文通信 -->
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<!-- 信任系統(tǒng)預(yù)裝 CA 證書(shū) -->
<certificates src="system" />
</trust-anchors>
</base-config>
而在 Android 9.0(API 28)及更高版本的默認(rèn)網(wǎng)絡(luò)安全性配置如下:
<!-- 默認(rèn)禁止所有明文通信 -->
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<!-- 信任系統(tǒng)預(yù)裝 CA 證書(shū) -->
<certificates src="system" />
</trust-anchors>
</base-config>
對(duì)比很容易發(fā)現(xiàn)衬横,在 Android 7.0(API 24)到 Android 8.1(API 27)按声,默認(rèn)不再信任用戶添加的 CA 證書(shū)膳犹,所以也就不再信任 Charles 和 Fiddler 抓包工具的證書(shū),所以抓取 HTTPS 包時(shí)才會(huì)失敗签则。而且在 Android 9.0(API 28)及更高版本上镣奋,不僅默認(rèn)只系統(tǒng)預(yù)裝的 CA 證書(shū),還默認(rèn)禁止所有明文通信(不允許 http 請(qǐng)求)怀愧。
解決方式
所以解決該問(wèn)題就需要應(yīng)用信任 Charles 和 Fiddler 抓包工具的證書(shū)抓包工具即可侨颈。
最簡(jiǎn)單的解決方式是使用 Android 6.0 以下的網(wǎng)絡(luò)安全性配置:
添加res/xml/network_security_config.xml
:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</base-config>
</network-security-config>
然后在清單文件中指向該文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
<application android:networkSecurityConfig="@xml/network_security_config"
... >
...
</application>
</manifest>
這種解決方式有一個(gè)安全風(fēng)險(xiǎn):正式版的應(yīng)用會(huì)有被他人抓包的風(fēng)險(xiǎn)余赢。
如何只在調(diào)試模式下允許抓包呢?
使用<debug-overrides>
即可實(shí)現(xiàn)只在android:debuggable
為true
時(shí)才生效的配置:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<!-- 支持 Android 7.0 以上調(diào)試時(shí)哈垢,信任 Charles 和 Fiddler 等用戶信任的證書(shū) -->
<debug-overrides>
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</debug-overrides>
</network-security-config>
網(wǎng)上有些解決方式是將 Charles 和 Fiddler 的證書(shū)添加到raw
文件夾下的方式也可以妻柒,但是繁瑣了點(diǎn)。
在 Android 9.0(API 28)以上允許部分 http 請(qǐng)求
最佳的解決方式肯定是全部使用 https 請(qǐng)求耘分,安全性更高举塔,如果有些請(qǐng)求或測(cè)試環(huán)境下還是需要使用 http 請(qǐng)求,需要在網(wǎng)絡(luò)安全性配置添加白名單:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<!-- 支持 Android 9.0 以上使用部分域名時(shí)使用 http -->
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">sample.domain</domain>
</domain-config>
<!-- 支持 Android 7.0 以上調(diào)試時(shí)求泰,信任 Charles 和 Fiddler 等用戶信任的證書(shū) -->
<debug-overrides>
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</debug-overrides>
</network-security-config>