You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android运行时动态修改Network Security Config是否可行?

问题描述

当前我的Network Security Config配置如下:

<network-security-config>
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <certificates src="system"/>
            <certificates src="user"/>
        </trust-anchors>
    </base-config>
</network-security-config>

我的应用需要连接多个服务器,其中部分使用自签名CA,且发布前无法预知具体CA信息,所以必须默认信任用户证书。但每次新增服务器、变更域名或证书都要发版,操作成本太高。

我想实现这样的逻辑:默认开启用户证书信任,首次连接服务器后,如果服务器返回类似trustUserCertificate=false的标识,就禁用/移除信任用户证书的能力。

我没找到解决方案,也没在Android文档里看到明确禁止该操作的说明,想知道这个需求能不能实现?如果不可行,有没有相关文档说明?


解决方案说明

这个需求是可以实现的,核心思路是放弃静态的network-security-config.xml配置,改用动态配置NetworkSecurityPolicy或者自定义SSL Socket Factory来实现信任策略的动态切换:

1. 动态修改NetworkSecurityPolicy(Android 7.0+)

从Android 7.0(API 24)开始,NetworkSecurityPolicy类提供了动态配置能力:

  • 初始状态下,设置策略允许信任系统+用户证书
  • 收到服务器返回的禁用指令后,更新策略为仅信任系统证书

示例代码逻辑:

// 初始状态:信任系统+用户证书
NetworkSecurityPolicy policy = NetworkSecurityPolicy.Builder.newBuilder()
        .addTrustAnchor(getSystemTrustAnchors(context))
        .addTrustAnchor(getUserTrustAnchors(context))
        .build();
NetworkSecurityPolicy.setInstance(policy);

// 收到服务器指令后,切换为仅信任系统证书
NetworkSecurityPolicy newPolicy = NetworkSecurityPolicy.Builder.newBuilder()
        .addTrustAnchor(getSystemTrustAnchors(context))
        .build();
NetworkSecurityPolicy.setInstance(newPolicy);

注:getSystemTrustAnchors和getUserTrustAnchors需要自行实现,通过KeyStore获取对应信任锚点。

2. 自定义SSL Socket Factory(兼容低版本)

如果需要兼容Android 7.0以下版本,建议自定义SSL Socket Factory,维护可动态切换的信任管理器:

  • 初始时,信任管理器包含系统CA和用户CA
  • 收到禁用指令后,替换为仅包含系统CA的信任管理器

示例代码逻辑:

// 初始信任管理器:系统+用户CA
TrustManager[] initialTrustManagers = createTrustManagers(true);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, initialTrustManagers, null);
OkHttpClient client = new OkHttpClient.Builder()
        .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) initialTrustManagers[0])
        .build();

// 切换为仅信任系统CA
TrustManager[] systemOnlyTrustManagers = createTrustManagers(false);
SSLContext newSslContext = SSLContext.getInstance("TLS");
newSslContext.init(null, systemOnlyTrustManagers, null);
client = client.newBuilder()
        .sslSocketFactory(newSslContext.getSocketFactory(), (X509TrustManager) systemOnlyTrustManagers[0])
        .build();

// 辅助方法:创建信任管理器
private TrustManager[] createTrustManagers(boolean includeUserCerts) throws Exception {
    KeyStore systemKeyStore = KeyStore.getInstance("AndroidCAStore");
    systemKeyStore.load(null, null);
    
    KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
    keyStore.load(null, null);
    Enumeration<String> systemAliases = systemKeyStore.aliases();
    while (systemAliases.hasMoreElements()) {
        String alias = systemAliases.nextElement();
        keyStore.setCertificateEntry(alias, systemKeyStore.getCertificate(alias));
    }
    
    if (includeUserCerts) {
        KeyStore userKeyStore = KeyStore.getInstance("AndroidUserStore");
        userKeyStore.load(null, null);
        Enumeration<String> userAliases = userKeyStore.aliases();
        while (userAliases.hasMoreElements()) {
            String alias = userAliases.nextElement();
            keyStore.setCertificateEntry(alias, userKeyStore.getCertificate(alias));
        }
    }
    
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(keyStore);
    return tmf.getTrustManagers();
}

注意事项

  • 动态切换信任策略后,需确保后续所有网络请求使用更新后的配置(比如重新创建OkHttpClient实例)
  • 该修改仅作用于当前应用,不会影响系统全局网络安全策略
  • 可以直接移除静态的network-security-config.xml文件,完全依赖动态配置实现需求

内容的提问来源于stack exchange,提问作者Claudiu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 02:10:36