Android 專案網路安全配置知識記錄
Android 在 Android 9(Pie)[android:targetSdkVersion = 28]之後將網路通訊預設配置為禁止了明文傳輸。所謂明文傳輸就是Http請求,所以如果我們開發版本高於 28 ,打包之後我們 app 中的 Http 請求都無法成功,將會丟擲
W/System.err: java.net.UnknownServiceException: CLEARTEXT communication to **** not permitted by network security policy
複製程式碼
的錯誤。
關於 Http 請求的限制歷史:
- 當 Android 6.0(Marshmallow)「(API 23)」釋出時,谷歌提出了清單檔案中配置:
android:usesCleartextTraffic
作為防止意外使用明文通訊的手段
<!-- 預設允許所有明文通訊 -->
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<!-- 信任系統預裝 CA 證照 -->
<certificates src="system" />
<!-- 信任使用者新增的 CA 證照,Charles 和 Fiddler 抓包工具安裝的證照屬於此類 -->
<certificates src="user" />
</trust-anchors>
</base-config>
複製程式碼
- Android 7.0 (Nougat) 通過引入Android網路安全配置 「Network Security Configuration」特性來過渡開發者配置這個屬性。Android 7.0 ~ 8.0 「(API 24) 至 (API 27)」 之間,客戶端仍可以使用 Http 請求。系統預設網路安全配置如下
<!-- 預設允許所有明文通訊 -->
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<!-- 信任系統預裝 CA 證照 -->
<certificates src="system" />
</trust-anchors>
</base-config>
複製程式碼
- Android 9(Pie)「(API 28)」以後系統預設強制禁止明文傳輸
usesCleartextTraffic = true
且預設只信任系統級別證照,也就是我們在手機,設定-> 加密與憑據 ->信任的憑據 -> 系統tab下的所有證照。
<!-- 預設禁止所有明文通訊 -->
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<!-- 信任系統預裝 CA 證照 -->
<certificates src="system" />
</trust-anchors>
</base-config>
複製程式碼
網路安全配置對我們開發者的影響
如果我們採用預設配置,在我們升級 targetSdkVersion >= 24
後,我們就會遇到 Https 請求無法通過抓包工具配置的證照進行抓包的問題。
當我們升級 targetSdkVersion >= 28
就會出現無法所有的 Http 請求都無法響應的問題。
通過上一節網路配置版本變化的描述過程我們會發現,原因在於,24 以上不再信任使用者證照了所以抓不了包了,28 以上無法進行http請求的原因是,系統預設不讓進行明文傳輸了。
什麼是網路安全配置?
上面解釋了這麼配置就可以解決我們遇到的無法抓包和無法進行http請求的問題,我們大概可以理解為這個「網路安全配置」其實就是駕馭在程式碼之外的一個配置檔案,程式讀取配置來決定要不要校驗http請求,是不是信任使用者證照。
可以看出 google 雖然做了限制,但是也給了開發者自由。接下來就要憑著開發者的良心辦事情了。
“最佳”實踐
當然為了響應 Google 爸爸的要求和使用者資訊保安考慮,我們應該儘快升級所有的伺服器域名為 Https 請求。但是對於有時候我們還是有一些域名為 Http 請求無法及時替換,就需要單獨配置了。而且就正式的 APP 包,我們並不希望可以讓其他人抓包,來給我們伺服器帶來安全隱患。
允許明文傳輸
- 方法一
允許明文傳輸有兩種配置方法第一個是在專案的主 module 的 AndroidManifest.xml
的 application 節點下配置
<application
...
<!--允許 -->
android:usesCleartextTraffic="true"
...>
...
</application>
複製程式碼
但是這個屬性在 Android 7.0 以後會被 android:networkSecurityConfig
屬性覆蓋。
- 方法二
新增在主工程中配置 res/xml/network_security_config.xml 如果沒有可以新建一個檔案。該配置會覆蓋系統預設配置。所以我們可在這裡配置我們自己的想要的網路配置。配置完成後我們需要在 AndroidManifest.xml
的 application 節點下配置
<application
...
<application android:networkSecurityConfig="@xml/network_security_config"
<!--7.0後會被覆蓋-->
<!--android:usesCleartextTraffic="true"-->
...>
...
</application>
複製程式碼
- 如何配置
network_security_config
可包含:
0 或 1 個 <base-config>
基本配置,也就是預設配置。
任意數量的 <domain-config>
可以規定任意域名的請求配置
0 或 1 個 <debug-overrides>
debug 模式下域名的配置,可用於除錯下進行一些獨立配置。
如果我們需要只需要支援某些域名下的明文傳輸,就可以利用 domain-config 來進行單獨配置
<network-security-config>
<!--允許有多個 domain-confing 該domain-config 下的domain 域名允許明文傳輸-->
<domain-config cleartextTrafficPermitted="true">
<!--includeSubdomains 是否是包含子域名-->
<domain includeSubdomains="true">example.com</domain>
<domain includeSubdomains="true">cdn.example2.com</domain>
</domain-config>
<!--除了domain-config 的標籤下的域名都不允許明文傳輸-->
<base-config cleartextTrafficPermitted="false" />
</network-security-config>
複製程式碼
信任使用者證照
比如我們需要允許debug模式下允許抓包,也就是信任 user 證照可以進行下面的配置
<network-security-config>
<!-- 支援 Android 7.0 以上除錯時,信任 Charles 等抓包工具的證照 -->
<debug-overrides>
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</debug-overrides>
...
</network-security-config>
複製程式碼
對於更多的配置資訊大家可以參照google文件:網路完全配置 一節。
在解決網路完全配置的時候突然想到了 Https 證照驗證的問題,為什麼我們APP本地沒有安裝證照,使用 OkHttp 也不用忽略證照驗證,同樣訪問大多數網站的時候我們也都沒有下載證照。就可以訪問了。其實是因為 OkHttp 對於通過CA機構頒發的伺服器證照,是預設通過校驗的。一些公司的自簽名證照就不行了。比如 12306。
#參考