React Native如何忽略HTTPS证书校验

最近在使用React Native开发项目的过程中,遇到这么一个问题,在安卓应用上调试的时候,正式域名访问没有任何问题,但是如果是内网或者本地域名且使用了自签证书,请求就不通了,由于我使用的是axios,会出现报错[AxiosError: Network Error],在碰到这个现象后第一反应就是https证书的问题,在尝试百度、Google搜索答案无果后,又尝试问了ChatGPT,发现他也并不知道怎么处理,但是会一本正经的给你胡诌,所以大家不要过分相信ChatGPT,不过幸运的是后来通过不断变换关键词最后在Google上找到了有效答案。

这个问题只在安卓应用上出现,IOS上则没有问题,问题的根源是因为在安卓机器上自签的ssl证书不受信任,所以要解决这个问题要么提供受信的证书,要么忽略证书校验,这里我们选择忽略证书校验,接下来我们看一下具体需要怎么做。

一、增加IgnoreSSLFactory.java

在RN项目安卓原生目录下/android/app/src/main/java/com/app名/新增文件IgnoreSSLFactory.java,并编写如下代码:

//IgnoreSSLFactory.java
package com.app名;  // 这里需要根据自己的应用做改动

import static android.content.ContentValues.TAG;

import android.util.Log;
import com.facebook.react.modules.network.OkHttpClientFactory;
import com.facebook.react.modules.network.OkHttpClientFactory;
import com.facebook.react.modules.network.OkHttpClientProvider;
import com.facebook.react.modules.network.ReactCookieJarContainer;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import okhttp3.CipherSuite;
import okhttp3.ConnectionSpec;
import okhttp3.OkHttpClient;
import okhttp3.TlsVersion;

public class IgnoreSSLFactory implements OkHttpClientFactory {

  private static final String TAG = "IgnoreSSLFactory";

  @Override
  public OkHttpClient createNewNetworkModuleClient() {
    try {
      final TrustManager[] trustAllCerts = new TrustManager[] {
        new X509TrustManager() {
          @Override
          public void checkClientTrusted(
            java.security.cert.X509Certificate[] chain,
            String authType
          ) throws CertificateException {}

          @Override
          public void checkServerTrusted(
            java.security.cert.X509Certificate[] chain,
            String authType
          ) throws CertificateException {}

          @Override
          public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return new java.security.cert.X509Certificate[] {};
          }
        },
      };
      final SSLContext sslContext = SSLContext.getInstance("SSL");
      sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
      final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
      OkHttpClient.Builder builder = new OkHttpClient.Builder()
        .connectTimeout(0, TimeUnit.MILLISECONDS)
        .readTimeout(0, TimeUnit.MILLISECONDS)
        .writeTimeout(0, TimeUnit.MILLISECONDS)
        .cookieJar(new ReactCookieJarContainer());
      builder.sslSocketFactory(
        sslSocketFactory,
        (X509TrustManager) trustAllCerts[0]
      );
      builder.hostnameVerifier(
        new HostnameVerifier() {
          @Override
          public boolean verify(String hostname, SSLSession session) {
            return true;
          }
        }
      );
      OkHttpClient okHttpClient = builder.build();
      return okHttpClient;
    } catch (Exception e) {
      Log.e(TAG, e.getMessage());
      throw new RuntimeException(e);
    }
  }
}

二、修改MainApplication.java

修改MainApplication.java文件,该文件位于/android/app/src/main/java/com/app名/目录下:

1、在头部新增如下代码:

import com.facebook.react.modules.network.OkHttpClientProvider;

2、在onCreate方法中新增如下代码:

OkHttpClientProvider.setOkHttpClientFactory(new IgnoreSSLFactory());

以我本地的项目为例,最终修改后的代码如下:

package com.app名;

import android.app.Application;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.defaults.DefaultReactNativeHost;
import com.facebook.soloader.SoLoader;
import java.util.List;

import com.facebook.react.modules.network.OkHttpClientProvider;

public class MainApplication extends Application implements ReactApplication {

  private final ReactNativeHost mReactNativeHost =
      new DefaultReactNativeHost(this) {
        @Override
        public boolean getUseDeveloperSupport() {
          return BuildConfig.DEBUG;
        }

        @Override
        protected List<ReactPackage> getPackages() {
          @SuppressWarnings("UnnecessaryLocalVariable")
          List<ReactPackage> packages = new PackageList(this).getPackages();
          // Packages that cannot be autolinked yet can be added manually here, for example:
          // packages.add(new MyReactNativePackage());
          return packages;
        }

        @Override
        protected String getJSMainModuleName() {
          return "index";
        }

        @Override
        protected boolean isNewArchEnabled() {
          return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
        }

        @Override
        protected Boolean isHermesEnabled() {
          return BuildConfig.IS_HERMES_ENABLED;
        }
      };

  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }

  @Override
  public void onCreate() {
    super.onCreate();
    SoLoader.init(this, /* native exopackage */ false);
    OkHttpClientProvider.setOkHttpClientFactory(new IgnoreSSLFactory());
    if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
      // If you opted-in for the New Architecture, we load the native entry point for this app.
      DefaultNewArchitectureEntryPoint.load();
    }
    ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
  }
}

在做了上述修改后,停止当前正在运行的RN项目,并重新启动该项目,会发现已经解决啦!

  • 支付宝二维码 支付宝
  • 微信二维码 微信
相关文章