Android 專案網路安全配置知識記錄

像一隻狗發表於2019-11-07

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。

#參考

相關文章