001/** 002 * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.mybatisflex.core.audit.http; 017 018import com.mybatisflex.core.util.StringUtil; 019import org.apache.ibatis.logging.LogFactory; 020 021import javax.net.ssl.*; 022import java.io.IOException; 023import java.io.InputStreamReader; 024import java.io.OutputStream; 025import java.io.UnsupportedEncodingException; 026import java.net.HttpURLConnection; 027import java.net.URL; 028import java.net.URLEncoder; 029import java.security.KeyManagementException; 030import java.security.NoSuchAlgorithmException; 031import java.security.NoSuchProviderException; 032import java.security.cert.CertificateException; 033import java.security.cert.X509Certificate; 034import java.util.Map; 035import java.util.Map.Entry; 036 037 038public class HttpUtil { 039 040 private static final String POST = "POST"; 041 042 043 private static String CHARSET = "UTF-8"; 044 private static int connectTimeout = 15000; // 连接超时,单位毫秒 045 private static int readTimeout = 15000; // 读取超时,单位毫秒 046 047 private static final SSLSocketFactory sslSocketFactory = initSSLSocketFactory(); 048 049 private static final TrustAnyHostnameVerifier trustAnyHostnameVerifier = new TrustAnyHostnameVerifier(); 050 051 /** 052 * https 域名校验 053 */ 054 private static class TrustAnyHostnameVerifier implements HostnameVerifier { 055 @Override 056 public boolean verify(String hostname, SSLSession session) { 057 return true; 058 } 059 } 060 061 /** 062 * https 证书管理 063 */ 064 private static class TrustAnyTrustManager implements X509TrustManager { 065 @Override 066 public X509Certificate[] getAcceptedIssuers() { 067 return null; 068 } 069 070 @Override 071 public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { 072 } 073 074 @Override 075 public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { 076 } 077 } 078 079 080 private static SSLSocketFactory initSSLSocketFactory() { 081 try { 082 TrustManager[] tm = {new HttpUtil.TrustAnyTrustManager()}; 083 SSLContext sslContext = SSLContext.getInstance("TLS"); // ("TLS", "SunJSSE"); 084 sslContext.init(null, tm, new java.security.SecureRandom()); 085 return sslContext.getSocketFactory(); 086 } catch (Exception e) { 087 throw new RuntimeException(e); 088 } 089 } 090 091 public static void setCharSet(String charSet) { 092 if (StringUtil.isBlank(charSet)) { 093 throw new IllegalArgumentException("charSet can not be blank."); 094 } 095 HttpUtil.CHARSET = charSet; 096 } 097 098 public static void setConnectTimeout(int connectTimeout) { 099 HttpUtil.connectTimeout = connectTimeout; 100 } 101 102 public static void setReadTimeout(int readTimeout) { 103 HttpUtil.readTimeout = readTimeout; 104 } 105 106 private static HttpURLConnection getHttpConnection(String url, String method, Map<String, String> headers) throws IOException, NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException { 107 URL _url = new URL(url); 108 HttpURLConnection conn = (HttpURLConnection) _url.openConnection(); 109 if (conn instanceof HttpsURLConnection) { 110 ((HttpsURLConnection) conn).setSSLSocketFactory(sslSocketFactory); 111 ((HttpsURLConnection) conn).setHostnameVerifier(trustAnyHostnameVerifier); 112 } 113 114 conn.setRequestMethod(method); 115 conn.setDoOutput(true); 116 conn.setDoInput(true); 117 118 conn.setConnectTimeout(connectTimeout); 119 conn.setReadTimeout(readTimeout); 120 121 conn.setRequestProperty("Content-Type", "application/json; charset=utf-8"); 122 123 if (headers != null && !headers.isEmpty()) { 124 for (Entry<String, String> entry : headers.entrySet()) { 125 conn.setRequestProperty(entry.getKey(), entry.getValue()); 126 } 127 } 128 129 return conn; 130 } 131 132 133 /** 134 * Send POST request 135 */ 136 public static String post(String url, Map<String, String> queryParas, String data, Map<String, String> headers) { 137 HttpURLConnection conn = null; 138 try { 139 conn = getHttpConnection(buildUrlQuery(url, queryParas), POST, headers); 140 conn.connect(); 141 142 if (data != null) { 143 try (OutputStream out = conn.getOutputStream()) { 144 out.write(data.getBytes(CHARSET)); 145 out.flush(); 146 } 147 } 148 return readString(conn); 149 } catch (IOException e) { 150 LogFactory.getLog(HttpUtil.class).error("post error.", e); 151 return null; 152 } catch (Exception e) { 153 throw new RuntimeException(e); 154 } finally { 155 if (conn != null) { 156 conn.disconnect(); 157 } 158 } 159 } 160 161 public static String post(String url, Map<String, String> queryParas, String data) { 162 return post(url, queryParas, data, null); 163 } 164 165 public static String post(String url, String data, Map<String, String> headers) { 166 return post(url, null, data, headers); 167 } 168 169 public static String post(String url, String data) { 170 return post(url, null, data, null); 171 } 172 173 private static String readString(HttpURLConnection conn) throws IOException { 174 try (InputStreamReader isr = new InputStreamReader(conn.getInputStream(), CHARSET)) { 175 StringBuilder ret = new StringBuilder(); 176 char[] buf = new char[1024]; 177 for (int num; (num = isr.read(buf, 0, buf.length)) != -1; ) { 178 ret.append(buf, 0, num); 179 } 180 return ret.toString(); 181 } 182 } 183 184 185 private static String buildUrlQuery(String url, Map<String, String> queryParas) { 186 if (queryParas == null || queryParas.isEmpty()) { 187 return url; 188 } 189 190 StringBuilder sb = new StringBuilder(url); 191 boolean isFirst; 192 if (url.indexOf('?') == -1) { 193 isFirst = true; 194 sb.append('?'); 195 } else { 196 isFirst = false; 197 } 198 199 for (Entry<String, String> entry : queryParas.entrySet()) { 200 if (isFirst) { 201 isFirst = false; 202 } else { 203 sb.append('&'); 204 } 205 206 String key = entry.getKey(); 207 String value = entry.getValue(); 208 if (StringUtil.isNotBlank(value)) { 209 try { 210 value = URLEncoder.encode(value, CHARSET); 211 } catch (UnsupportedEncodingException e) { 212 throw new RuntimeException(e); 213 } 214 } 215 sb.append(key).append('=').append(value); 216 } 217 return sb.toString(); 218 } 219 220 221} 222 223 224 225 226 227