本文原文來自Android developer官方文檔。html
藉助網絡安全配置功能,應用能夠在一個安全的聲明性配置文件中自定義其網絡安全設置,而無需修改應用代碼。您能夠針對特定網域和特定應用配置這些設置。此功能的主要特性以下所示:android
網絡安全配置功能使用一個 XML 文件,您能夠在該文件中指定應用的設置。您必須在應用的清單中包含一個指向該文件的條目。如下代碼摘自一個清單文件,演示瞭如何建立此條目:算法
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
<application android:networkSecurityConfig="@xml/network_security_config"
... >
...
</application>
</manifest>
複製代碼
應用可能須要信任自定義的 CA 集,而不是平臺默認值。出現此狀況的最多見緣由包括:後端
默認狀況下,來自全部應用的安全鏈接(使用 TLS 和 HTTPS 之類的協議)均信任預裝的系統 CA,而面向 Android 6.0(API 級別 23)及更低版本的應用默認狀況下還會信任用戶添加的 CA 存儲區。應用可使用 base-config(應用範圍的自定義)或 domain-config(網域範圍的自定義)自定義本身的鏈接。安全
假設您要鏈接到使用自簽名 SSL 證書的主機,或者鏈接到其 SSL 證書是由您信任的非公共 CA(如公司的內部 CA)簽發的主機。服務器
res/xml/network_security_config.xml:網絡
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
<domain includeSubdomains="true">example.com</domain>
<trust-anchors>
<certificates src="@raw/my_ca"/>
</trust-anchors>
</domain-config>
</network-security-config>
複製代碼
以 PEM 或 DER 格式將自簽名或非公共 CA 證書添加到 res/raw/my_ca。app
若是應用不想信任系統信任的全部 CA,則能夠自行指定,縮減要信任的 CA 集。這樣可防止應用信任任何其餘 CA 簽發的欺詐性證書。dom
限制可信 CA 集的配置與針對特定網域信任自定義 CA 類似,不一樣的是,前者要在資源中提供多個 CA。ide
res/xml/network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
<domain includeSubdomains="true">secure.example.com</domain>
<domain includeSubdomains="true">cdn.example.com</domain>
<trust-anchors>
<certificates src="@raw/trusted_roots"/>
</trust-anchors>
</domain-config>
</network-security-config>
複製代碼
以 PEM 或 DER 格式將可信 CA 添加到 res/raw/trusted_roots。請注意,若是使用 PEM 格式,文件必須僅包含 PEM 數據,沒有額外的文本。您還能夠提供多個 元素,而不是隻提供一個元素。
應用可能須要信任系統不信任的其餘 CA,出現此狀況的緣由多是系統還未包含此 CA,或 CA 不符合添加到 Android 系統中的要求。應用能夠經過爲一個配置指定多個證書源來實現此目的。
res/xml/network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config>
<trust-anchors>
<certificates src="@raw/extracas"/>
<certificates src="system"/>
</trust-anchors>
</base-config>
</network-security-config>
複製代碼
調試經過 HTTPS 鏈接的應用時,您可能須要鏈接到沒有爲生產服務器提供 SSL 證書的本地開發服務器。爲了支持此操做,而不對應用的代碼進行任何修改,您可使用 debug-overrides 指定僅在 android:debuggable 爲 true 時纔信任的僅調試 CA。一般,IDE 和編譯工具會自動爲非發佈版本設置此標記。
這比通常的條件代碼更安全,由於出於安全考慮,應用商店不接受被標記爲可調試的應用。
res/xml/network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<debug-overrides>
<trust-anchors>
<certificates src="@raw/debug_cas"/>
</trust-anchors>
</debug-overrides>
</network-security-config>
複製代碼
此部分的指南僅適用於面向 Android 8.1(API 級別 27)或更低級別的應用。從 Android 9(API 級別 28)開始,系統默認狀況下已停用明文支持。
打算鏈接到僅使用安全鏈接的目標的應用能夠選擇不對這些目標提供明文(使用未加密 HTTP 協議而非 HTTPS)支持。此選項有助於防止應用因外部源(如後端服務器)提供的網址發生變化而意外迴歸。如需瞭解詳情,請參閱 NetworkSecurityPolicy.isCleartextTrafficPermitted()。
例如,應用可能須要確保全部與 secure.example.com 的鏈接始終是經過 HTTPS 完成,以防止來自惡意網絡的敏感流量。
res/xml/network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">secure.example.com</domain>
</domain-config>
</network-security-config>
複製代碼
通常狀況下,應用信任全部預裝 CA。若是有預裝 CA 簽發欺詐性證書,則應用將面臨被中間人攻擊的風險。有些應用經過限制信任的 CA 集或經過固定證書,選擇限制其接受的證書集。
要固定證書,您能夠經過按公鑰的哈希值(X.509 證書的 SubjectPublicKeyInfo)提供證書集。而後,只有至少包含一個已固定公鑰的證書鏈纔有效。
請注意,固定證書時,您應始終包含一個備份密鑰,這樣,當您被強制切換到新密鑰或更改 CA 時(固定到某個 CA 證書或該 CA 的中間證書時),應用的鏈接性不會受到影響。不然,您必須推送應用更新以恢復鏈接性。
此外,能夠設置證書固定的到期時間,在該時間以後再也不固定證書。這有助於防止還沒有更新的應用出現鏈接性問題。不過,設置證書固定的到期時間可能會繞過證書固定。
res/xml/network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
<domain includeSubdomains="true">example.com</domain>
<pin-set expiration="2018-01-01">
<pin digest="SHA-256">7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=</pin>
<!-- backup pin -->
<pin digest="SHA-256">fwza0LRMXouZHRC8Ei+4PyuldPDcf3UKgO/04cDM1oE=</pin>
</pin-set>
</domain-config>
</network-security-config>
複製代碼
未在特定配置中設置的值將繼承值。此行爲容許進行更復雜的配置,同時又能保證配置文件易於閱讀。
若是未在特定條目中設置值,將使用來自更通用條目中的值。例如,未在 domain-config 中設置的值將從父級 domain-config(若是已嵌套)或者 base-config(若是未嵌套)中獲取。未在 base-config 中設置的值將使用平臺默認值。
例如,考慮全部與 example.com 的子網域的鏈接必須使用自定義 CA 集。此外,容許指向這些網域的明文流量,但鏈接到 secure.example.com 時除外。經過在 example.com 的配置中嵌套 secure.example.com 的配置,不須要重複 trust-anchors。
res/xml/network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
<domain includeSubdomains="true">example.com</domain>
<trust-anchors>
<certificates src="@raw/my_ca"/>
</trust-anchors>
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">secure.example.com</domain>
</domain-config>
</domain-config>
</network-security-config>
複製代碼
網絡安全配置功能使用 XML 文件格式。文件的總體結構如如下代碼示例所示:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config>
<trust-anchors>
<certificates src="..."/>
...
</trust-anchors>
</base-config>
<domain-config>
<domain>android.com</domain>
...
<trust-anchors>
<certificates src="..."/>
...
</trust-anchors>
<pin-set>
<pin digest="...">...</pin>
...
</pin-set>
</domain-config>
...
<debug-overrides>
<trust-anchors>
<certificates src="..."/>
...
</trust-anchors>
</debug-overrides>
</network-security-config>
複製代碼
如下部分將介紹語法與文件格式的其餘詳細信息。
可包含:
語法:
<base-config cleartextTrafficPermitted=["true" | "false"]>
...
</base-config>
複製代碼
可包含:
說明:
目標不在 domain-config 涵蓋範圍內的全部鏈接所使用的默認配置。 未設置的任何值均使用平臺默認值。
面向 Android 9(API 級別 28)及更高版本應用的默認配置以下所示:
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
複製代碼
面向 Android 7.0(API 級別 24)到 Android 8.1(API 級別 27)的應用的默認配置以下所示:
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
複製代碼
面向 Android 6.0(API 級別 23)及更低版本應用的默認配置以下所示:
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</base-config>
複製代碼
語法:
<domain includeSubdomains=["true" | "false"]>example.com</domain>
複製代碼
可包含:
說明
用於按照 domain 元素的定義鏈接到特定目標的配置。 請注意,若是有多個 domain-config 元素涵蓋某個目標,將使用匹配網域規則最具體(最長)的配置。
語法:
<domain includeSubdomains=["true" | "false"]>example.com</domain>
複製代碼
屬性:
includeSubdomains
若是爲 "true",此網域規則將與相應網域及全部子網域(包括子網域的子網域)匹配。不然,該規則僅適用於精確匹配項。
語法:
<debug-overrides>
...
</debug-overrides>
複製代碼
可包含:
說明:
在 android:debuggable 爲 "true" 時將應用的替換,IDE 和編譯工具生成的非發佈版本一般屬於此狀況。在 debug-overrides 中指定的信任錨會添加到全部其餘配置,而且當服務器的證書鏈使用其中一個僅調試信任錨時不固定證書。若是 android:debuggable 爲 "false",則徹底忽略此部分。
語法:
<trust-anchors>
...
</trust-anchors>
複製代碼
可包含:
說明:
用於安全鏈接的信任錨集。
語法:
<certificates src=["system" | "user" | "raw resource"] overridePins=["true" | "false"] />
說明:
用於 trust-anchors 元素的 X.509 證書集。
屬性:
src
CA 證書的來源。每一個證書可爲下列狀態之一:
overridePins
指定此來源的 CA 是否繞過證書固定。若是爲 "true",則不針對由此來源的某個 CA 簽署的證書鏈固定證書。這對於調試 CA 或測試對應用的安全流量進行中間人攻擊 (MiTM) 很是有用。
默認值爲 "false",除非在 debug-overrides 元素中另外指定(在這種狀況下,默認值爲 "true")。
語法:
<pin-set expiration="date">
...
</pin-set>
複製代碼
可包含:
說明:
一組公鑰固定。要信任某個安全鏈接,信任鏈中必須有一個公鑰位於固定集中。有關固定格式,請參閱 <pin>。
屬性:
expiration
採用 yyyy-MM-dd 格式的日期,證書固定會在該日期過時,於是將中止固定證書。若是未設置該屬性,則證書固定不會過時。 設置到期時間有助於防止未得到其固定集更新(例如,在用戶停用應用更新時)的應用出現鏈接問題。
語法:
<pin digest=["SHA-256"]>base64 encoded digest of X.509
SubjectPublicKeyInfo (SPKI)</pin>
複製代碼
屬性:
digest
用於生成證書固定的摘要算法。目前僅支持 "SHA-256"。