在Android React Native中忽略SSL证书检查

12

我目前正在使用React Native开发Android应用,通过fetch()函数来进行API请求。但是,由于端点没有SSL证书,请求失败了。在iOS上,我通过修改一些Xcode文件来解决这个问题。 有没有办法在Android上忽略SSL证书检查?

3个回答

2
/**
 * Disables the SSL certificate checking for new instances of {@link HttpsURLConnection} This has been created to
 * aid testing on a local box, not for use on production.
 */
private static void disableSSLCertificateChecking() {
    TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        @Override
        public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
            // Not implemented
        }

        @Override
        public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
            // Not implemented
        }
    } };

    try {
        SSLContext sc = SSLContext.getInstance("TLS");

        sc.init(null, trustAllCerts, new java.security.SecureRandom());

        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    } catch (KeyManagementException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
}

在这里找到了这篇文章:https://gist.github.com/aembleton/889392。不太确定它是否有效,但至少是一个开始!


2
嗨,我应该把它粘贴在哪个文档中? - Matheus Cabral

1

我也遇到了同样的问题。我使用了rn-fetch-blob库,并将下面的代码粘贴到index.js中。

import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
import RNFetchBlob from 'rn-fetch-blob';

AppRegistry.registerComponent(appName, () => App);
const Fetch = RNFetchBlob.polyfill.Fetch
// replace built-in fetch
window.fetch = new Fetch({
     // enable this option so that the response data conversion handled automatically
     auto : true,
    // when receiving response data, the module will match its Content-Type header
   // with strings in this array. If it contains any one of string in this array, 
  // the response body will be considered as binary data and the data will be stored
  // in file system instead of in memory.
  // By default, it only store response data to file system when Content-Type 
  // contains string `application/octet`.
  binaryContentTypes : [
    'image/',
    'video/',
    'audio/',
    'foo/',
 ],
 trusty : true
}).build()

如果您在Android中仍然遇到SSL握手问题,则尝试使用以下解决方案。并从MainApplication.java中的onCreate()调用以下函数:
 import android.annotation.SuppressLint;
 import java.security.SecureRandom;
 import java.security.cert.X509Certificate;

 import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLSession;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.X509TrustManager;

 public class MainApplication extends Application implements ReactApplication {
    @Override
    public void onCreate() {
         super.onCreate();
         handleSSLHandshake();
         SoLoader.init(this, /* native exopackage */ false);
         initializeFlipper(this); // Remove this line if you don't want Flipper enabled
    }

    /**
    * Enables https connections
    */
   @SuppressLint("TrulyRandom")
    public static void handleSSLHandshake() {
        try {
            TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
               public X509Certificate[] getAcceptedIssuers() {
                  return new X509Certificate[0];
               }

              @Override
              public void checkClientTrusted(X509Certificate[] certs, String authType) {
              }

               @Override
               public void checkServerTrusted(X509Certificate[] certs, String authType) {
               }
           }};

           SSLContext sc = SSLContext.getInstance("SSL");
           sc.init(null, trustAllCerts, new SecureRandom());


     HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
          HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
               @Override
               public boolean verify(String arg0, SSLSession arg1) {
                  return true;
              }
           });
      } catch (Exception ignored) {
      }
    } 
 }

letsencrypt在2014年开始发放免费证书。与其为开发设置创建有效的SSL证书,你们却削弱了应用程序的安全性,并制作了糟糕的代码片段,这些代码片段被成千上万的初级开发人员使用(复制/粘贴)。你确定你已经正确地解决了这个问题吗?难道不应该为你的开发服务器创建有效的SSL证书,而不是破坏应用程序吗? - Maxim Sagaydachny
是的,@MaximSagaydachny需要为开发制作有效的SSL证书,但我正在处理前端,所以为了解决这个问题,我使用了上述解决方案。我不知道后端人员为什么不使用有效的SSL证书。 - Pankaj Negi
这个解决方案对我很有效。正在使用React-native版本0.62。 - Pinki Dhakad

0

注意:这是一个不太规范的解决方案

你可以修补webview包

前往node_modules/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewManager.java

onReceivedSslError中更改handler.cancel()为handler.proceed(),像这样

@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
   // before: handler.cancel();
  handler.proceed();
}

如果你想要进行补丁打包,那么你可以使用 patch-package 库。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接