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/