网络安全配置
网络安全配置功能允许您在一个安全的声明式配置文件中自定义应用的网络安全设置,而无需修改应用代码。您可以为特定域名或应用定制这些设置。该功能的主要能力包括:
- 自定义信任锚:可定制应用安全连接所信任的证书颁发机构 (CA),例如信任特定的自签名证书或限制应用信任的公共CA范围。
- 仅限调试的覆盖:在不影响安装版本的安全性的情况下,调试应用中的安全连接。
- 明文流量选择退出:防止应用误用明文(未加密)的流量。
- 证书固定(Pinning):限制应用的安全连接只能使用特定证书。
添加网络安全配置文件
该功能使用XML文件来指定应用的设置。您需要在应用的 manifest
文件中添加一个入口,指向该配置文件,例如:
<manifest ... >
<application android:networkSecurityConfig="@xml/network_security_config" ...>
...
</application>
</manifest>
自定义受信的CA
有时您可能希望应用信任自定义的CA集合,而不是使用系统默认的CA,例如:
- 连接到使用自签名证书的服务器
- 仅信任特定的CA,避免信任所有预装的CA
- 信任系统中未包含的CA
您可以通过 base-config
(用于整个应用的配置)或 domain-config
(用于特定域的配置)自定义应用连接。
配置自定义CA
假设您希望连接到一个使用自签名SSL证书或非公共CA(如公司内部CA)的主机。您可以在 res/xml/network_security_config.xml
中添加配置,例如:
<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>
将自签名或非公共CA证书(PEM或DER格式)添加到 res/raw/my_ca
。
限制受信的CA集合
如果您不想让应用信任系统所有CA,可以指定一个较小的受信CA集合,防止因其他CA发布的伪造证书带来的风险。示例代码如下:
<network-security-config>
<domain-config>
<domain includeSubdomains="true">secure.example.com</domain>
<trust-anchors>
<certificates src="@raw/trusted_roots"/>
</trust-anchors>
</domain-config>
</network-security-config>
信任额外的CA
某些情况下,您可能希望应用信任系统中未包含的CA。您可以在 network_security_config.xml
中指定多个证书源:
<network-security-config>
<base-config>
<trust-anchors>
<certificates src="@raw/extracas"/>
<certificates src="system"/>
</trust-anchors>
</base-config>
</network-security-config>
配置调试用的CA
当调试连接HTTPS时,您可能需要连接到没有生产服务器SSL证书的本地开发服务器。您可以使用 debug-overrides
指定调试用CA,这些CA仅在 android:debuggable
为 true
时信任:
<network-security-config>
<debug-overrides>
<trust-anchors>
<certificates src="@raw/debug_cas"/>
</trust-anchors>
</debug-overrides>
</network-security-config>
选择退出明文流量
如果您的应用仅应使用安全连接(如HTTPS),您可以选择退出对明文流量的支持,避免外部资源意外更改URL导致的回归问题。如下示例中,对 secure.example.com
禁用明文流量:
<network-security-config>
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">secure.example.com</domain>
</domain-config>
</network-security-config>
证书固定
通常应用信任所有预装的CA,但您可以通过证书固定来限制受信证书集,只允许指定的公钥。建议提供备份密钥,以防更换密钥或CA。
示例代码如下:
<network-security-config>
<domain-config>
<domain includeSubdomains="true">example.com</domain>
<pin-set expiration="2018-01-01">
<pin digest="SHA-256">7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=</pin>
<pin digest="SHA-256">fwza0LRMXouZHRC8Ei+4PyuldPDcf3UKgO/04cDM1oE=</pin>
</pin-set>
</domain-config>
</network-security-config>
配置继承行为
配置文件的各级设置会自动继承未设置的父级值。例如,将 example.com
的子域配置为自定义CA集合,并且禁用 secure.example.com
的明文流量:
<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文件格式。文件的整体结构如下:
<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>
以下部分描述了文件格式的语法和其他细节。
<network-security-config>
可以包含:
- 0或1个
<base-config>
- 任意数量的
<domain-config>
- 0或1个
<debug-overrides>
<base-config>
语法:
<base-config cleartextTrafficPermitted=["true" | "false"]>
...
</base-config>
可以包含:
<trust-anchors>
描述:所有不在 <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-config>
语法:
<domain-config cleartextTrafficPermitted=["true" | "false"]>
...
</domain-config>
可以包含:
- 1个或多个
<domain>
- 0或1个
<trust-anchors>
- 0或1个
<pin-set>
- 任意数量的嵌套
<domain-config>
描述:用于特定目标的连接配置,由 <domain>
元素定义。如果多个 <domain-config>
元素覆盖同一目标,则使用匹配规则最长的配置。
<domain>
语法:
<domain includeSubdomains=["true" | "false"]>example.com</domain>
属性:
includeSubdomains
:如果为“true”,则此域规则适用于该域及所有子域,包括子域的子域。否则,仅适用于精确匹配。
<debug-overrides>
语法:
<debug-overrides>
...
</debug-overrides>
可以包含:
- 0或1个
<trust-anchors>
描述:当 android:debuggable
为“true”时应用的覆盖,通常适用于IDE和构建工具生成的非发布版本。debug-overrides
中指定的信任锚将添加到所有其他配置中,并且当服务器的证书链使用这些仅限调试的信任锚时,不会执行证书固定。
<trust-anchors>
语法:
<trust-anchors>
...
</trust-anchors>
可以包含:
- 任意数量的
<certificates>
描述:用于安全连接的信任锚集合。
<certificates>
语法:
<certificates src=["system" | "user" | "raw resource"] overridePins=["true" | "false"] />
描述:信任锚元素的X.509证书集合。
属性:
src
:CA证书的来源。每个证书可以是以下之一:- 指向包含X.509证书的原始资源ID,证书必须以DER或PEM格式编码。PEM格式的文件必须不包含额外的非PEM数据(如注释)。
- “system”表示预装的系统CA证书。
- “user”表示用户添加的CA证书。
overridePins
:指定此来源的CA是否绕过证书固定。如果为“true”,则不会在由此来源的CA签名的证书链上执行固定。这对调试CA或测试中间人攻击非常有用。默认值为“false”,除非在debug-overrides
元素中指定,则默认值为“true”。
<pin-set>
语法:
<pin-set expiration="date">
...
</pin-set>
可以包含:
- 任意数量的
<pin>
描述:一组公钥固定。要信任的安全连接,信任链中的公钥必须在固定集中。
属性:
expiration
:以yyyy-MM-dd
格式表示的日期,表示固定的到期时间,过期后将禁用固定。如果未设置该属性,则固定不会过期。到期设置有助于防止未更新固定集的应用程序出现连接问题,例如用户禁用应用更新时。
<pin>
语法:
<pin digest=["SHA-256"]>
base64编码的X.509 SubjectPublicKeyInfo (SPKI)
</pin>
属性:
digest
:生成固定时使用的摘要算法。目前仅支持“SHA-256”。
通过这种方式,您可以灵活地管理应用的网络安全设置,确保在安全连接中使用受信任的证书,保护用户的数据和隐私。