Android 7.0新增之网络安全性配置

/ 0评 / 3

Network Security Config

当我们使用Fiddler等工具抓包的时候,我们往往需要在设备上面安装一个证书,这样我们才能抓取https的数据,类似于中间人攻击,抓包工具使用自己的证书去加解密,如果客户端没有对证书进行校验的话,那么就无法防范这种情况。但是在Android 7.0(sdk>=24)以后,如果你的targetSdkVersion>=24,那么默认是只能使用系统的CA,这样我们就无法使用Fiddler等工具进行抓包。

当我们第一次开始请求后台数据,查看log可以看到:NetworkSecurityConfig: No Network Security Config specified, using platform default。

系统默认行为

targetSdkVersion>=24    如果没有额外配置,默认只信任系统CA,如果我们使用Fiddler抓包,会提示CertPathValidatorException,因为Fiddler的证书是我们自己安装的

targetSdkVersion < 24    默认信任系统上面安装的CA。包括用户自己安装的,Network Security Config配置无效

自定义配置

1、在xml文件夹下创建一个network_security_config.xml文件(名字可自定义)

2、在application标签下进行配置

<manifest ... >
    <application 
        android:networkSecurityConfig="@xml/network_security_config"
     ... >
        ...
    </application>
</manifest>

配置规则

1、大致模板

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
  <base-config cleartextTrafficPermitted=["true" | "false"]>//应用范围的默认配置,只能配置一次。
	<trust-anchors>//信任锚,就是信任数据源。【base-config中只能存在一个trust-anchors】
		<certificates src="..."/>//证书。【可以存在多个】
		...
	</trust-anchors>
  </base-config>

  <domain-config cleartextTrafficPermitted=["true" | "false"]>//域名级配置,针对待访问的网站域名,【可以存在多个】
	<domain includeSubdomains=["true" | "false"]>android.com</domain>//includeSubdomains是否包含子域名 【可以存在多个】
	...
	<trust-anchors>【domain-config中只能存在一个trust-anchors】
		<certificates src="..."/>
		...
	</trust-anchors>
	<pin-set>//证书公钥设置,用于证书固定,一般可以不用配置,除非确定证书长期有效。
		<pin digest="...">...</pin>
		...
	</pin-set>
	...//如果域名之间存在父子关系,可以进行嵌套设置,同时对于证书的使用,可以用includeSubdomains对父域名设置,使证书具有继承属性。
  </domain-config>
  ...
  <debug-overrides>//DEBUG调试时采用的信任源,只在DEBUG时起作用。
	<trust-anchors>
		<certificates src="..."/>
		...
	</trust-anchors>
  </debug-overrides>
</network-security-config>

2、<base-config>

base-config是默认的配置,当domain-config一个都不匹配的时候,使用base-config

cleartextTrafficPermitted:是否允许明文传输

<base-config cleartextTrafficPermitted=["true" | "false"]>
    ...
</base-config>

3、trust-anchors

用于表示被信任的证书集合

<trust-anchors>
...
</trust-anchors>

4、certificates 

用来表示一个X.509证书

<certificates src=["system" | "user" | "raw resource"]
              overridePins=["true" | "false"] />

src: CA 证书的来源。每个证书可为下列状态之一

指向包含 X.509 证书的文件的原始资源 ID。证书必须以 DER 或 PEM 格式编码。如果为 PEM 证书,则文件不得包含额外的非 PEM 数据,例如注释。

用系统自带 CA 证书的 "system"

用于用户安装的 CA 证书的 "user"

自定义证书:PEM 或 DER 格式的 CA 证书添加到 res/raw/my_ca

<?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>

5、domain-config

配置具体的域名,使用domain 标签声明域名,可以有多个,使用trust-anchors标签声明信任的CA集合,domain-config下面只能有一个trust-anchors

<domain-config cleartextTrafficPermitted=["true" | "false"]>
    ...
</domain-config>

6、domain 

定义一个域名,includeSubdomains是否包含子域名,

<domain includeSubdomains=["true" | "false"]>android.com</domain>

pin-set与pin不做讨论。更多详情可以查看官方文档

7、其他

通过上面我们可以知道,base-config与domain-config都有一个属性cleartextTrafficPermitted,它代表的含义为是否允许进行明文传输(http),当设置为flase的时候,会直接报错,请求失败

其他

最后还是再说一句,由于网络安全性配置是7.0的新增特性,所以7.0以下配置了也是无效的!!!!

参考链接

https://developer.android.com/training/articles/security-config?hl=zh-cn#domain-config

https://iacn.me/2018/03/14/network-security-configuration-newer-than-android-n/

https://blog.csdn.net/lz8362/article/details/78289930

发表评论

您的电子邮箱地址不会被公开。