React Native Android端动态SSL固定失效问题求助
针对你遇到的iOS正常、Android端通过RemoteConfig传递密钥后SSL固定不生效的问题,结合你的代码和场景,给出以下具体排查方向:
检查OkHttpClient的替换时机
React Native默认的NetworkModule会在应用初始化阶段创建OkHttpClient实例。如果你的RemoteConfig是在MainApplication.onCreate之后(比如通过JS桥接异步获取)才拿到密钥,此时替换SSLPinningFactory已经晚了——原来的客户端已经在使用中。
解决:要么提前同步获取RemoteConfig(在NetworkModule初始化前),要么在拿到密钥后,重新设置OkHttpClientFactory并重启相关网络请求实例,确保后续请求使用新的带Pin的客户端。验证证书Pin的格式正确性
你的代码中拼接了"sha256/" + pinningKey,要确认RemoteConfig返回的pin值是否已经包含sha256/前缀。如果后端返回的是完整的Pin字符串(比如sha256/xxxxxxx),这里会导致重复前缀,直接造成Pin不匹配。
验证方式:打印最终生成的key值,和目标域名的实际证书Pin对比(用命令行生成正确Pin:openssl s_client -connect 目标域名:443 | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64)。确认自定义Factory是否被RN实际使用
确保你在拿到密钥后,正确调用了NetworkModule.setOkHttpClientFactory(new SSLPinningFactory(pinningKey)),而不是仅仅创建了SSLPinningFactory实例。如果是在JS桥接的回调中设置Factory,还要确认该逻辑是否被执行,且没有被后续的RN初始化流程覆盖。检查通配符域名的匹配范围
你的代码中使用*.asfaf.com作为主机名,注意OkHttp的通配符仅匹配一级子域(比如api.asfaf.com符合,但api.sub.asfaf.com不符合)。如果你的请求涉及多层子域,需要添加对应的主机名规则,比如同时添加*.asfaf.com和*.sub.asfaf.com。添加调试日志定位失败原因
在OkHttpClient构建时添加异常拦截器,捕获Pin验证失败的具体日志:OkHttpClient.Builder client = new OkHttpClient.Builder() // 原有配置... .certificatePinner(certificatePinner) .addInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { try { return chain.proceed(chain.request()); } catch (SSLPeerUnverifiedException e) { Log.e("SSLPinningDebug", "Pin验证失败: " + e.getMessage()); throw e; } } });通过日志可以明确是Pin不匹配、域名不匹配还是其他问题。
确认激活状态的逻辑正确性
检查SSL固定激活状态的判断逻辑:是否在激活状态为true时才应用CertificatePinner,为false时使用默认客户端。避免因为激活状态传递错误,导致Pin没有被实际应用。核对RN版本的兼容性
不同RN版本的OkHttpClient替换方式可能有差异,比如部分版本需要通过ReactHttpClientFactory或者在ReactInstanceManager构建中配置。如果你使用的是较新版本RN(0.60+),确认你的替换方式符合官方文档的要求。
内容的提问来源于stack exchange,提问作者volkandincer

