配置了网安策略,为什么抓包工具还能抓到明文
移动端的安全测试里,最常见的一个红榜问题就是:抓包工具(如 Charles / Fiddler)只要能装上证书,就能直接看穿你的 HTTPS 请求体。开发者的第一反应是“我明明用了 HTTPS 啊”。用 HTTPS 只能保证传输过程中的加密,但在中间人攻击(MITM)场景下,如果客户端不校验服务端的真实身份,随便一个自制证书都能蒙混过关。
这就轮到证书锁定(SSL Pinning)出场了。在 HarmonyOS 7 中,你不必手写底层 Socket 校验逻辑,系统网络配置提供了一套机制,可以直接在配置层把非法的证书拦住。

网络安全配置的入口
在 AppScope 下的 resources 目录中,新建一个 base/profile/network_config.json 文件。你需要在这个文件里告诉系统,哪些域名需要做特殊校验。这不需要动任何 ArkTS 代码,纯粹是配置声明。
json5
{
"network-security-config": {
"base-config": {
"cleartextTrafficPermitted": false
},
"domain-config": [
{
"domains": [
{ "include-subdomains": true, "name": "api.yourdomain.com" }
],
"pin-set": {
"expiration": "2026-01-01",
"pin": [
{
"digest-algorithm": "sha256",
"digest": "b2w6jXkZ4M3d...你的证书指纹..."
}
]
}
}
]
}
}
这段 JSON 配置的信息量很大。cleartextTrafficPermitted: false 全面禁用了 HTTP 明文请求,这能应付大部分的合规扫描。domain-config 则指定了你的 API 域名,并开启了 pin-set。digest 字段就是证书的 SPKI(Subject Public Key Info)哈希,常见的算法选 sha256。expiration 则是这个配置的过期时间,建议设得比证书有效期稍微长一点,以备应急。
绑定配置到模块
写好了 JSON,系统并不会自动认,必须在 module.json5 的 module 对象中,将配置文件指定过去。
json5
{
"module": {
"name": "entry",
"type": "entry",
"metadata": [
{
"name": "ohos.net.network_security_config",
"resource": "$profile:network_config"
}
]
}
}
注意 name 字段是固定的 ohos.net.network_security_config,不要写错字母。resource 则指向刚才创建的 JSON 文件。
配完之后,重新打包运行。此时再用抓包工具去拦截,你会发现你的 API 请求直接断开了。因为客户端在握手阶段发现服务端出示的证书(抓包工具自签发的)指纹,和 network_config.json 里写的指纹对不上,校验失败,直接掐断了连接。
指纹提取与轮换的坑
指纹从哪里来?打开你的服务端域名,在浏览器或者命令行里导出证书的公钥,计算其 SHA256 哈希值。注意,不要导出整张证书的哈希,要导出公钥(Public Key)的哈希。因为整张证书是包含有效期的,证书一续期,哈希就变了,所有的旧版本应用都会瞬间断网。
即使使用的是公钥哈希,证书轮换仍然是一个随时可能引爆的炸弹。如果服务端更换了证书密钥对,而客户端 network_config.json 里还是旧的哈希,请求会毫不留情地失败。
防御这种作死操作的办法是,在 pin 数组里放至少两个指纹。一个是当前的公钥指纹,另一个是备用的公钥指纹(通常提前生成,在下一轮证书更新时启用)。当服务端完成切换后,老版本的客户端凭借备用指纹依然能正常连接。
json5
"pin": [
{ "digest-algorithm": "sha256", "digest": "当前指纹..." },
{ "digest-algorithm": "sha256", "digest": "备用指纹..." }
]
兼容性与降级处理
网络安全配置在系统层面生效,它拦截的是所有的网络请求,包括 @ohos.net.http 和底层的第三方框架请求。但如果你在应用里使用了自研的 C++ 网络库,而且它绕过了系统底层的证书校验链,那么这套配置对它是无效的。这种场景下,安全策略要在自己的网络库里单独实现。
另外,如果遇到了测试环境抓包需要,或者紧急情况下的降级,可以在 Debug 构建变体下使用一份不含 pin-set 的配置,但要确保 Release 构建一定包含了完整的配置,不要在打包脚本里搞混了。
更多推荐

所有评论(0)