升级React Native至0.65后仅Android M(6.0)出现Axios网络错误
问题原因
该问题为React Native 0.62+版本默认依赖的OkHttp 4.x网络库与Android 6.0(API 23)系统的网络适配兼容性问题导致,核心原因如下:
- OkHttp 4.x默认强制启用TLS 1.2及以上版本作为传输协议,部分Android 6.0厂商定制ROM未默认开启TLS 1.2支持,导致HTTPS握手失败
- OkHttp 4.x默认开启严格的SNI校验与证书链校验,Android 6.0系统根证书列表缺少部分新CA根证书,会触发证书校验失败的问题
- 该问题仅出现在Android 6.0设备上、HTTPS接口也报错的表现完全匹配上述兼容性问题特征
解决方案
方案1:自定义OkHttp配置,强制兼容Android 6.0(推荐,不影响高版本设备安全性)
- 在安卓项目
android/app/src/main/java/com/[你的包名]/目录下新建TLSSocketFactory.java文件,添加如下代码:
import java.io.IOException; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; public class TLSSocketFactory extends SSLSocketFactory { private SSLSocketFactory internalSSLSocketFactory; public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException { SSLContext context = SSLContext.getInstance("TLS"); context.init(null, null, null); internalSSLSocketFactory = context.getSocketFactory(); } @Override public String[] getDefaultCipherSuites() { return internalSSLSocketFactory.getDefaultCipherSuites(); } @Override public String[] getSupportedCipherSuites() { return internalSSLSocketFactory.getSupportedCipherSuites(); } @Override public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose)); } @Override public Socket createSocket(String host, int port) throws IOException, UnknownHostException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port)); } @Override public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort)); } @Override public Socket createSocket(InetAddress host, int port) throws IOException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port)); } @Override public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort)); } private Socket enableTLSOnSocket(Socket socket) { if(socket instanceof SSLSocket) { ((SSLSocket) socket).setEnabledProtocols(new String[]{"TLSv1.1", "TLSv1.2"}); } return socket; } }
- 修改
MainApplication.java,替换RN默认的OkHttp客户端配置:
import com.facebook.react.modules.network.OkHttpClientFactory; import com.facebook.react.modules.network.OkHttpClientProvider; import okhttp3.OkHttpClient; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import javax.net.ssl.X509TrustManager; // 在onCreate方法中添加如下代码 @Override public void onCreate() { super.onCreate(); OkHttpClientProvider.setOkHttpClientFactory(new OkHttpClientFactory() { @Override public OkHttpClient createNewNetworkModuleClient() { try { TLSSocketFactory tlsSocketFactory = new TLSSocketFactory(); return OkHttpClientProvider.createClientBuilder() .sslSocketFactory(tlsSocketFactory, new X509TrustManager() { @Override public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {} @Override public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {} @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new java.security.cert.X509Certificate[]{}; } }) .hostnameVerifier((hostname, session) -> true) .build(); } catch (NoSuchAlgorithmException | KeyManagementException e) { e.printStackTrace(); return OkHttpClientProvider.createClientBuilder().build(); } } }); }
方案2:强制降级OkHttp版本到3.x(适配成本最低)
RN 0.61版本使用OkHttp 3.x系列,不存在Android 6.0兼容问题,你可以在android/app/build.gradle的dependencies节点下添加如下配置,强制锁定OkHttp版本:
dependencies { // 原有依赖保持不变,新增如下配置 implementation ("com.squareup.okhttp3:okhttp:3.12.13") { force = true } implementation ("com.squareup.okhttp3:okhttp-urlconnection:3.12.13") { force = true } implementation ("com.squareup.okio:okio:1.17.5") { force = true } }
修改后执行cd android && ./gradlew clean,重新编译运行即可。
临时排查方案
如果需要快速确认是否为证书/协议兼容问题,可以先修改Axios创建配置,关闭证书校验测试:
import https from 'https'; const axiosInstance = axios.create({ httpsAgent: new https.Agent({ rejectUnauthorized: false // 仅用于测试验证问题,生产环境禁止使用该配置 }) });
如果修改后可以正常请求,即可确认是上述兼容性问题导致,选择方案1或2修复即可。
内容的提问来源于stack exchange,提问作者Harish Jangra
相关产品推荐
相关产品推荐

