当前位置:首页 > Web开发 > 正文

二是从HostnameVerifier入手. 4.2.1 HostnameVerifier 先说个简单的

2024-07-17 Web开发

1 概述

OkHttp配置HTTPS访谒,核心为以下三个部分:

sslSocketFactory()

HostnameVerifier

X509TrustManager

第一个是ssl套接字工厂,第二个用来验证主机名,第三个是证书信任器打点类.通过OkHttp实现HTTPS访谒需要本身实现以上三部分.此外还简单提及了处事器真个部署,用的是Tomcat9,最后是一些常见问题的可能解决方案.

2 OkHttp介绍

OkHttp是一款开源的措置惩罚惩罚网络请求的轻量级框架,有Square公司孝敬,用于替代HttpUrlConnection与Apache HttpClient,目前Github上有36.4k的star.长处有

共享socket,HTTP/2撑持所有连接到同一个主机的请求共享socket

连接池可以减少请求延迟

缓存响应数据减少反复的网络请求

自动措置惩罚惩罚gzip压缩

总的来说OkHttp是一款撑持get/post请求,撑持文件上传/下载的优秀的HTTP框架.

3 筹备事情

一台处事器

一个域名

一个证书

什么?都没有?买!
固然证书可以不用买,可以使用openssl之类的工具生成,不过自签名的证书后面验证的时候会有点麻烦,建议还是采办.

4 OkHttp部分 4.1 暴力方案 public static String test() { OkHttpClient client = new OkHttpClient.Builder() .sslSocketFactory(createSSLSocketFactory(), new TrustAllCerts()) .hostnameVerifier(new TrustAllHostnameVerifier()).build(); String url = "https://xxxxxxx"; //改削本钱身的url Request request = new Request.Builder().url(url).build(); Call call = build.newCall(request); Response response = call.execute(); if(response.body() != null) { String result = response.body().string(); //措置惩罚惩罚result } } private static class TrustAllCerts implements X509TrustManager { public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {} public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {} public X509Certificate[] getAcceptedIssuers() {return new X509Certificate[0];} } private static class TrustAllHostnameVerifier implements HostnameVerifier { public boolean verify(String hostname, SSLSession session) { return true; } } private static SSLSocketFactory createSSLSocketFactory() { SSLSocketFactory ssfFactory = null; try { SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, new TrustManager[]{new TrustAllCerts()}, new SecureRandom()); ssfFactory = sc.getSocketFactory(); } catch (Exception e) { e.printStackTrace(); } return ssfFactory; }

这是一种暴力的方案,看类名就知道了,信任所有的证书与主机:

public boolean verify(String hostname, SSLSession session) { return true; }

这个要领直接返回true,也就是信任所有的主机.

public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {} public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}

这里两个check函数没有做任何的事情,暗示接受任意的客户端与处事真个证书.这样写的话相当于是使用了一个没用的TrustManager,这样还不如不加密,不保举使用.

4.2 保举方案

从两方面入手改削,一是从X509TrustManager入手,二是从HostnameVerifier入手.

4.2.1 HostnameVerifier

先说个简单的,这里主要是验证主机名,简单的话,可以如下实现:

HostnameVerifier hnv = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { if("".equals(hostname)){ return true; } else { HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier(); return hv.verify(hostname, session); } } };

这里验证主机名是就返回true,实现得对照简单,业务庞大的话可以结合配置中心,黑/白名单等动态校验.

4.2.2 X509TrustManager

这里其实有两种方法,一种是以流的方法添加信任证书:

private static X509TrustManager trustManagerForCertificates(InputStream in) throws GeneralSecurityException { CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); Collection<? extends Certificate> certificates = certificateFactory.generateCertificates(in); if (certificates.isEmpty()) { throw new IllegalArgumentException("expected non-empty set of trusted certificates"); } char[] password = "password".toCharArray(); // 这里可以使用任意暗码 KeyStore keyStore = newEmptyKeyStore(password); int index = 0; for (Certificate certificate : certificates) { String certificateAlias = Integer.toString(index++); keyStore.setCertificateEntry(certificateAlias, certificate); } // Use it to build an X509 trust manager. KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance( KeyManagerFactory.getDefaultAlgorithm()); keyManagerFactory.init(keyStore, password); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(keyStore); TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) { throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers)); } return (X509TrustManager) trustManagers[0]; }

完整代码见文末.这里把工具类的要领实现成了静态,挪用时可以直接:

OKHTTP.send("https://xxxxx");

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/web/27385.html