package com.emato.common.utils.oms; import okhttp3.*; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.net.ssl.*; import java.io.IOException; import java.io.InputStream; import java.security.KeyStore; import java.security.SecureRandom; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.concurrent.TimeUnit; /** * @author Scott Chen * @date 2017/3/13 */ public class OkHttpUtils { private static final Logger logger = LoggerFactory.getLogger(OkHttpUtils.class); public static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json;charset=UTF-8"); public static final MediaType MEDIA_TYPE_XML = MediaType.parse("application/xml;charset=UTF-8"); public static final MediaType MEDIA_TYPE_TEXT_HTML = MediaType.parse("text/html;charset=UTF-8"); private static final MediaType MEDIA_TYPE_FORM= MediaType.parse("application/x-www-form-urlencoded"); private static final String SSL = "SSL"; public static final int CONNECT_TIME_OUT = 20; public static final int READ_TIME = 30; public static final int WRITE_TIME = 30; private static final ThreadLocal okHttpClientThreadLocal = new ThreadLocal<>(); private static final ThreadLocal okHttpClientSslThreadLocal = new ThreadLocal<>(); /** * 禁止调用无参构造 */ private OkHttpUtils() {} /** * 默认http * @return */ private static OkHttpClient okHttpClient(){ return okHttpClient(null); } /** * https 和 http * @param ssl 如果需要SSL认证https, ssl值为SSL, 如果ssl为空, 则为http * @return */ private static OkHttpClient okHttpClient(String ssl){ return StringUtils.isNotBlank(ssl) && SSL.equals(ssl) ? okHttpInstanceSsl() : okHttpInstance(); } /** * https 和 http * 如果要信息所有证书, * ssl必须为SSL, * ignoreHostnameVerifier为true, * InputStream... certificates为null * * @param ssl * @param ignoreHostnameVerifier 是否忽略Hostname验证 * @param certificates 证书流 * @return */ private static OkHttpClient okHttpClient(String ssl, boolean ignoreHostnameVerifier, InputStream... certificates){ return StringUtils.isNotBlank(ssl) && SSL.equals(ssl) ? okHttpInstanceSsl(ignoreHostnameVerifier, certificates) : okHttpInstance(); } /** * OkHttpClient 实例 * @return */ private static OkHttpClient okHttpInstance() { OkHttpClient client = okHttpClientThreadLocal.get(); if (client == null) { synchronized (OkHttpUtils.class) { OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.connectTimeout(CONNECT_TIME_OUT, TimeUnit.SECONDS) .readTimeout(READ_TIME, TimeUnit.SECONDS) .writeTimeout(WRITE_TIME, TimeUnit.SECONDS) .retryOnConnectionFailure(true); client = builder.build(); okHttpClientThreadLocal.set(client); } } return client; } /** * OkHttpClient ssl 实例 * 忽略Hostname验证, 并信息所有证书 * @return */ private static OkHttpClient okHttpInstanceSsl() { return okHttpInstanceSsl(true, new InputStream[]{}); } /** * OkHttpClient ssl 实例 * 如果要信息所有证书, InputStream... certificates为null * @param ignoreHostnameVerifier 是否忽略Hostname验证 * @param certificates 证书流 * @return */ private static OkHttpClient okHttpInstanceSsl(boolean ignoreHostnameVerifier, InputStream... certificates) { OkHttpClient client = okHttpClientSslThreadLocal.get(); if (client == null) { synchronized (OkHttpUtils.class) { X509TrustManager[] trustManager = buildX509TrustManager(certificates); SSLSocketFactory sslSocketFactory = buildSSLSocketFactory(trustManager); OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.connectTimeout(CONNECT_TIME_OUT, TimeUnit.SECONDS) .readTimeout(READ_TIME, TimeUnit.SECONDS) .writeTimeout(WRITE_TIME, TimeUnit.SECONDS) .retryOnConnectionFailure(true); //是否忽略host验证 if (ignoreHostnameVerifier) { builder.hostnameVerifier(getHostnameVerifier()); } builder.sslSocketFactory(sslSocketFactory, trustManager[0]) .retryOnConnectionFailure(true); client = builder.build(); okHttpClientSslThreadLocal.set(client); } } return client; } //------------------------------ build RequestBody ------------------------------ public static RequestBody buildRequestBody(MediaType mediaType, String json) { return RequestBody.create(mediaType,json ); } public static RequestBody buildRequestBody(String key, Object value) { if (org.apache.commons.lang3.StringUtils.isBlank(key)) { return null; } Map param = new HashMap<>(); param.put(key, value); return buildRequestBody(param); } public static RequestBody buildMapStringRequestBody(Map params) { FormBody.Builder builder = new FormBody.Builder(); Iterator> iterator = params.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry entry = iterator.next(); builder.add(entry.getKey(), entry.getValue()); } return builder.build(); } /** * 构造RequestBody * * @param params * @return */ public static RequestBody buildRequestBody(Map params) { FormBody.Builder builder = new FormBody.Builder(); Iterator> iterator = params.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry entry = iterator.next(); builder.add(entry.getKey(), JacksonUtils.toJsonStr(entry.getValue())); } return builder.build(); } //------------------------------ build Request ------------------------------ /** * 以字符串数据构建 * @param json * @param url * @param type * @return */ public static Request buildRequest(String json, String url, String type) { //默认JSON MediaType mediaType = MEDIA_TYPE_JSON; type = StringUtils.isBlank(type) ? "" : type; json = StringUtils.isBlank(json) ? "" : json; if (type.equalsIgnoreCase("text_html")) { mediaType = MEDIA_TYPE_TEXT_HTML; }else if (type.equalsIgnoreCase("form")) { mediaType = MEDIA_TYPE_FORM; }else if (type.equalsIgnoreCase("xml")) { mediaType = MEDIA_TYPE_XML; } RequestBody body = buildRequestBody(mediaType, json); return buildRequest(body, url); } public static Request buildStringRequest(Map param, String url) { return buildRequest(buildMapStringRequestBody(param), url); } /** * 构建Request * @param param * @param url * @return */ public static Request buildRequest(Map param, String url) { return buildRequest(buildRequestBody(param), url); } /** * 构建Request * @param key * @param value * @param url * @return */ public static Request buildRequest(String key, Object value, String url) { return buildRequest(buildRequestBody(key, value), url); } /** * 构建Request * @param body * @param url * @return */ public static Request buildRequest(RequestBody body, String url) { return new Request.Builder() .url(url) .post(body) .build(); } //------------------------------ post ------------------------------ public static String post(String json, String url, String type, String ssl) { return post(buildRequest(json, url, type), ssl); } public static String post(String key, Object value, String url, String ssl) { return post(buildRequest(key, value, url), ssl); } public static String postString(Map param, String url, String ssl) { return post(buildStringRequest(param, url), ssl); } public static String post(Map param, String url, String ssl) { return post(buildRequest(param, url), ssl); } /** * 同步访问,返回结果字符串 * 可能超时 * * @param request * @param ssl * @return * @throws IOException */ public static String post(Request request, String ssl) { String result = ""; try { Response response = okHttpClient(ssl).newCall(request).execute(); if (response.isSuccessful()) { result = response.body().string(); } else { logger.error("okhttp3 post failed."); } } catch (IOException e) { logger.error("okhttp3 post throw IOException, {}", e.getMessage()); } return result; } /** * 同步访问,返回Response * 可能超时 * * @param request * @param ssl * @return * @throws IOException */ public static String postReturnResponse(Request request, String ssl) { try { return okHttpClient(ssl).newCall(request).execute().body().string(); } catch (IOException e) { logger.error("okhttp3 post throw IOException, {}", e.getMessage()); } return null; } /** * 异步访问,回调结果 * @param request * @param ssl * @param responseCallback */ public static void asyncPostCallback(Request request, String ssl, Callback responseCallback) { okHttpClient(ssl).newCall(request).enqueue(responseCallback); } /** * 异步访问,无结果返回 * @param request * @param ssl */ public static void asyncPost(Request request, String ssl) { okHttpClient(ssl).newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { } }); } //------------------------------ ssl ------------------------------ /** * 获取主机验证 HostnameVerifier * @return */ public static HostnameVerifier getHostnameVerifier() { return new HostnameVerifier() { @Override public boolean verify(String s, SSLSession sslSession) { return true; } }; } /** * 自定义证书 * * @param certificates * @return */ private static KeyStore generateKeyStore(InputStream... certificates) { try { CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null); int index = 0; if (certificates !=null && certificates.length > 0) { for (InputStream certificate : certificates) { String certificateAlias = Integer.toString(index++); keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate)); try { if (certificate != null) { certificate.close(); } } catch (IOException e) { } } } return keyStore; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 证书管理 * 信任所有证书 * @return */ private static X509TrustManager[] buildX509TrustManager(){ return buildX509TrustManager(new InputStream[]{}); } /** * 证书管理 * 如果要信任所有证书,InputStream... certificates为null * @param certificates 证书文件流 * @return */ private static X509TrustManager[] buildX509TrustManager(InputStream... certificates) { try { if (certificates == null) { // 信任所有证书 return new X509TrustManager[]{ new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[]{}; } } }; } // 信任自定义证书 KeyStore keyStore = generateKeyStore(certificates); 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; } catch (Exception e) { e.printStackTrace(); } return null; } private static SSLSocketFactory buildSSLSocketFactory() { return buildSSLSocketFactory((InputStream)null); } private static SSLSocketFactory buildSSLSocketFactory(InputStream... certificates) { try { TrustManager[] trustManager = buildX509TrustManager(certificates); return buildSSLSocketFactory(trustManager); } catch (Exception e) { e.printStackTrace(); } return null; } private static SSLSocketFactory buildSSLSocketFactory(TrustManager[] trustManager) { try { if (trustManager == null) { throw new IllegalStateException("TrustManager is null"); } SSLContext sslContext = SSLContext.getInstance(SSL); sslContext.init(null, trustManager, new SecureRandom()); return sslContext.getSocketFactory(); } catch (Exception e) { e.printStackTrace(); } return null; } }