react-native for android https证书认证

来源:互联网 发布:java nio相关书籍 编辑:程序博客网 时间:2024/06/05 11:33

react-native for android https证书认证

react-native项目中,前端的请求其实都是调用原生插件发起的。在android端,使用的是okHttp。

这篇博客是在react-native 0.47 + okhttp3 + tomcat的基础上讲解在本地生成自签名的https证书并给本地tomcat配置,再在android端配置证书认证,在前端fetch时请求本地https请求通过。

1、首先是https证书生成
我采用的是时jks文件,但我想jks可以,keystone文件应该也是可以的。jks和keystone文件生成过程不做描述。
利用jks文件来签发证书
在jks文件 同级目录执行命令:
keytool -export -alias server -file server.cer -keystore server.jks
这里写图片描述
-alias 后面填你选择的jks文件的 alias
-file 后面填你要生成的.cer文件的文件名
-keystore 后面填你选择的jks文件名
正确后回车则会要你输入口令,之后会在同级目录生成cer文件
这一步生成的cer文件就是用于android认证的证书文件

2、tomcat配置https

在你tomcat/conf/server.xml中,找到端口号8443的标签,默认是被屏蔽的,放开并修改为如下:
<Connector        port="8443"        protocol="org.apache.coyote.http11.Http11Protocol"        SSLEnabled="true"        maxThreads="150"        scheme="https"        secure="true"        clientAuth="false"        sslProtocol="TLS"        keystoreFile="这里写你上面jks文件的路径(D:\test\test.jks)"        keystorePass="这里写你jks文件的密码(123456)"    />

接下来你可以访问
https://localhost:8443/
浏览器第一次应该会显示如下
这里写图片描述
因为我们采用的是自签名的证书。点继续跳转到网页
如果出现tomcat的默认界面,说明访问正常,而且因为是我们自签名的证书,浏览器会显示会 不信任。

ok,http在pc浏览器请求通过,接下来就是在andorid应用内部。

3、react-native 项目应用在android端设置https

首页你可以直接在前端fetch你自己的https地址,你会发现返回结果是network request failed,因为你访问的是一个不可信的https地址。如果你去请求一个由权威机构颁发的证书的地址则可以请求到数据,比如你可以请求CSDN地址看看。

开始andorid端设置,首页前端的请求其实都是调用的原生插件,我们初始化一个rn项目时,会发现在MainApplication中会引入一个默认的package。
new MainReactPackage()
你点进去看会发现这里都是一些原生插件,如图片加载、权限模块、网络请求等等。
其中的 return new NetworkingModule(context);
就是封装的关于okhttp到前端调用的插件。

里面有多个构造函数,我们传进去的只有有个context,然后它又通过this指向四个参数的构造,其实多个构造最终指向的都是四个入参的构造函数,而传过去的OkHttpclient都是通过OkHttpClientProvider.createOkHttpClient()
而且OkHttpClientProvider还提供了替换clien对象的方法
OkHttpClientProvider.replaceOkHttpClient(client);

总之有两种方法
1、修改NetworkingModule.java文件
在里面为client添加证书认证。
如果你不知道怎么修改源码,那就需要第二种方法。

2、修改原生请求的引用
之前说了,它是把原生请求模块封装在NetworkingModule中,然后在MainreactPackage中引用, 我们完全可以把NetworkingModule.java文件移出来,然后在MainreactPackage中引用我们自己写的NetworkingModule.java类就行了。

将NetworkingModule.java文件的内容复制出来,将里面的
OkHttpClientProvider.createOkHttpClient() 都替换为
OkHttpClientProvider.getOkHttpClient()即可。
同时其中有个RequestBodyUtil.java类无法导入,也需要我们复制出来

再重写MainReactPackage.java类。
也是复制内容,修改其中NetworkingModule的引用即可。

然后将MainApplication中的MainReactPackage的引用修改即可。

前面这些修改都只是改了client对象的获取而且。 接下来才是对client对象的修改,即添加证书认证

// 证书认证private void setCertificates(OkHttpClient.Builder client, InputStream... certificates) {    try{      CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");      KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());      keyStore.load(null);      int index = 0;      for(InputStream certificate : certificates) {        String certificateAlias = Integer.toString(index++);        keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));        if(certificate != null) {          certificate.close();        }      }      SSLContext sslContext = SSLContext.getInstance("TLS");      TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());      trustManagerFactory.init(keyStore);      sslContext.init(              null,              trustManagerFactory.getTrustManagers(),              new SecureRandom()      );      client.sslSocketFactory(sslContext.getSocketFactory());    }catch (Exception e) {      Log.d("===", e.getMessage());      e.printStackTrace();    }  }// 设置client对象并替换private void httpsSetting() {    OkHttpClient.Builder client = new OkHttpClient.Builder()            .connectTimeout(30 * 1000, TimeUnit.MILLISECONDS)            .readTimeout(30 * 1000, TimeUnit.MILLISECONDS)            .writeTimeout(30 * 1000, TimeUnit.MILLISECONDS)            .cookieJar(new ReactCookieJarContainer());    try{      setCertificates(client, getAssets().open("这里填你放入assets目录下的cer文件名(test.cer)"));      client.hostnameVerifier(new HostnameVerifier() {        @Override        public boolean verify(String hostname, SSLSession session) {        // hostname 为服务器地址。ip或域名          Log.d("============", hostname);          return true;        }      });    } catch (IOException e) {      e.printStackTrace();    }    OkHttpClient.Builder builder = OkHttpClientProvider.enableTls12OnPreLollipop(client);    // 将上面设置了认证的client对象替换    OkHttpClientProvider.replaceOkHttpClient(builder.build());  }

然后只要在MainApplication中的oncreate生命周期调用httpsSetting()即可。你在前端就能通过fetch获取你tomcat里的数据

其实还有服务器对客户端的证书认证。即达到双向认证。

待续