移动端的安全测试里,最常见的一个红榜问题就是:抓包工具(如 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 构建一定包含了完整的配置,不要在打包脚本里搞混了。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐