8、网络传输安全:HTTPS强制与证书锁定、请求头与Body中敏感信息脱敏、第三方SDK网络行为监控

网络传输安全这块,说白了就是你的App在跟服务器“说话”的时候,不能被别人偷听、篡改或者冒充。我见过太多App,本地数据存得挺严实,结果一联网全裸奔了。这章咱们就聊聊怎么把网络这条通道守好。

8.1 HTTPS强制:别给中间人留机会

先问个问题:你的App还在用HTTP吗?如果答案是肯定的,那基本上等于把用户数据写在明信片上寄出去。任何经过路由器的设备都能看到内容。

我个人习惯是,在AndroidManifest里直接禁止明文流量。从Android 9(API 28)开始,系统默认就禁止了明文HTTP,但很多老项目还在用,或者混着用。我建议你一步到位:

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

然后在 res/xml/network_security_config.xml 里这样写:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="false">
        <trust-anchors>
            <certificates src="system" />
        </trust-anchors>
    </base-config>
</network-security-config>

嗯,这里要注意:如果你有特殊场景必须用HTTP(比如某些老旧的CDN),可以用 <domain-config> 单独放行,但一定要做白名单,别图省事直接开全局。

⚠️ 避坑指南: 我曾经接手过一个项目,开发同学为了调试方便,在AndroidManifest里加了 android:usesCleartextTraffic="true",上线前忘了删。结果用户数据在公共WiFi下被中间人抓了个精光。所以我的建议是:用 networkSecurityConfig 的方式,别依赖那个全局开关。

8.2 证书锁定:防的就是“合法”的中间人

HTTPS就安全了吗?不一定。你想想看,如果用户的设备里被装了个根证书(比如某些企业监控软件、或者恶意App),那中间人攻击照样能解密你的HTTPS流量。这就是为什么需要证书锁定(Certificate Pinning)。

证书锁定的原理很简单:客户端只信任你指定的那个证书或公钥,其他的一概不认。就算系统信任了某个CA签发的假证书,你的App也不买账。

我推荐用OkHttp的 CertificatePinner 来实现:

OkHttpClient client = new OkHttpClient.Builder()
    .certificatePinner(new CertificatePinner.Builder()
        .add("api.yourdomain.com", 
             "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
        .add("api.yourdomain.com", 
             "sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=")
        .build())
    .build();

这里有个坑:证书是会过期的,或者你可能会换证书。如果你只锁定一个证书,一旦换证,所有旧版本App就全挂了。我的做法是:

  • 锁定两个公钥:一个当前用的,一个备份的。备份的可以是你未来计划换的证书,或者根CA的公钥。
  • 留个后门:在App里内置一个远程配置开关,万一出问题可以临时关闭锁定,通过热修复推送新配置。
💡 小技巧: 获取证书SHA256指纹可以用这条命令:
openssl s_client -connect api.yourdomain.com:443 -servername api.yourdomain.com 2>/dev/null | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64

8.3 请求头与Body中的敏感信息脱敏

HTTPS加密了传输通道,但日志呢?抓包工具呢?你想想看,如果开发人员在调试时把完整的请求日志打到了控制台,或者上传到了日志平台,那Token、手机号、身份证号这些信息就等于公开了。

我个人习惯是,在网络层统一做脱敏处理。具体来说:

8.3.1 请求头脱敏

常见的敏感Header包括:AuthorizationCookieX-Token 等。在打印日志或上报网络数据时,必须把这些字段的值替换掉。

public class SafeHttpLogger implements HttpLoggingInterceptor.Logger {
    private static final Set<String> SENSITIVE_HEADERS = new HashSet<>(Arrays.asList(
        "Authorization", "Cookie", "Set-Cookie", "X-Token", "X-Session-Id"
    ));

    @Override
    public void log(String message) {
        // 对包含敏感Header的行进行脱敏
        for (String header : SENSITIVE_HEADERS) {
            if (message.contains(header + ": ")) {
                message = message.replaceAll(
                    "(?i)(" + header + ":\\s*)(.*)", 
                    "$1******"
                );
            }
        }
        Log.d("OkHttp", message);
    }
}

8.3.2 Body脱敏

Body里的敏感字段更隐蔽。比如登录接口的密码、注册接口的手机号、支付接口的银行卡号。我的做法是定义一个注解,标记哪些字段需要脱敏:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Sensitive {
    SensitiveType type() default SensitiveType.DEFAULT;
    
    enum SensitiveType {
        DEFAULT,    // 全部掩码
        PARTIAL,    // 部分掩码,如 138****1234
        EMAIL       // 邮箱掩码
    }
}

// 然后在序列化时统一处理
public class SensitiveSerializer {
    public static String toJson(Object obj) {
        // 反射遍历字段,对标记了@Sensitive的字段做掩码处理
        // 具体实现略...
    }
}
🔑 关键原则: 脱敏要在最底层做,不要等到上层业务逻辑再处理。因为日志、崩溃上报、网络监控这些都可能在你不知情的情况下把原始数据传出去。

8.4 第三方SDK网络行为监控

这是个大问题。你的App里集成了多少第三方SDK?统计、推送、广告、社交分享……每个SDK都可能在你不知情的情况下发起网络请求。GDPR和个人信息保护法都要求,App必须对第三方SDK的数据收集行为负责。

我建议从两个层面来监控:

8.4.1 网络代理层监控

利用OkHttp的 EventListener 或者 NetworkInterceptor,可以监控所有经过OkHttp的请求。但问题是,很多第三方SDK用的是自己的网络库,不走OkHttp。

这时候可以用Android的 ProxySelector 或者 NetworkCapabilities 来做全局监控。更彻底的做法是:

  • 抓包分析:在测试阶段,用Charles或Wireshark抓取所有流量,逐个SDK排查它们发了什么请求、传了什么数据。
  • VPNService:在App内启动一个本地VPN,拦截所有流量。但这个方法对性能有影响,而且Google Play可能审核不通过。

8.4.2 代码层面的SDK行为审计

我个人习惯是,在集成每个SDK之前,先做一次代码审计:

  1. 反编译SDK的jar/aar:用jadx或Bytecode Viewer打开,搜索 HttpURLConnectionOkHttpSocket 等关键字。
  2. 检查URL白名单:看SDK请求了哪些域名,有没有把设备信息、位置信息等敏感数据传出去。
  3. 查看隐私政策:确认SDK的隐私政策是否跟你App的隐私政策一致。
⚠️ 我曾经踩过的坑: 有个广告SDK,表面上只请求广告素材,但实际上它会在后台偷偷上传用户的WiFi列表和已安装App列表。我们是在做合规审计时用抓包工具发现的。从那以后,我养成了一个习惯:每个新SDK集成后,必须用抓包工具跑一遍全功能测试。

8.5 本章知识体系

下面这张图总结了网络传输安全的核心要点,你可以对照着检查自己的App:

网络传输安全知识体系 🔒 HTTPS强制 • 禁止明文流量(cleartextTrafficPermitted=false) • 使用 networkSecurityConfig 精确控制 • 白名单放行特殊场景,拒绝全局HTTP 🔑 证书锁定 • 锁定公钥而非证书,方便换证 • 至少锁定两个公钥(当前+备份) • 配合远程配置,留紧急开关 🛡️ 敏感信息脱敏 • 请求头:Authorization、Cookie等掩码 • Body:密码、手机号、身份证等脱敏 • 在序列化/日志层统一处理 📡 SDK网络监控 • 抓包分析:Charles/Wireshark全流量 • 代码审计:反编译检查网络请求 • 建立SDK行为白名单机制 目标:传输加密 + 身份验证 + 数据脱敏 + 行为透明

网络传输安全这件事,说白了就是“防人之心不可无”。你永远不知道用户处在什么样的网络环境下,也不知道第三方SDK会不会“越界”。所以我的建议是:把安全措施做在默认配置里,而不是等出了问题再补。

📌 一句话总结: HTTPS是底线,证书锁定是保险,脱敏是习惯,监控是手段。四者缺一不可。

公众号:蓝海资料掘金营,微信deep3321