package com.isoftstone.core.util;import java.io.BufferedReader;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.PrintWriter;import java.io.UnsupportedEncodingException;import java.net.HttpURLConnection;import java.net.URL;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Map;import javax.net.ssl.HostnameVerifier;import javax.net.ssl.HttpsURLConnection;import javax.net.ssl.SSLSession;import javax.servlet.http.HttpServletResponse;import org.apache.commons.lang.StringUtils;/** * https post发送工具 * ?* @author 超神之巅 * */public class HttpsTool { ???private static final String LINE_SEPARATOR = System.getProperty("line.separator"); ???????static HostnameVerifier hv = new HostnameVerifier() { ???????public boolean verify(String urlHostName, SSLSession session) { ???????????System.out.println("Warning: URL Host: " + urlHostName + " vs. " ???????????????????+ session.getPeerHost()); ???????????return true; ???????} ???}; ???????private static void trustAllHttpsCertificates() throws Exception { ???????javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1]; ???????javax.net.ssl.TrustManager tm = new miTM(); ???????trustAllCerts[0] = tm; ???????javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext ???????????????.getInstance("SSL"); ???????sc.init(null, trustAllCerts, null); ???????javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc ???????????????.getSocketFactory()); ???} ???static class miTM implements javax.net.ssl.TrustManager, ???????????javax.net.ssl.X509TrustManager { ???????public java.security.cert.X509Certificate[] getAcceptedIssuers() { ???????????return null; ???????} ???????public boolean isServerTrusted( ???????????????java.security.cert.X509Certificate[] certs) { ???????????return true; ???????} ???????public boolean isClientTrusted( ???????????????java.security.cert.X509Certificate[] certs) { ???????????return true; ???????} ???????public void checkServerTrusted( ???????????????java.security.cert.X509Certificate[] certs, String authType) ???????????????throws java.security.cert.CertificateException { ???????????return; ???????} ???????public void checkClientTrusted( ???????????????java.security.cert.X509Certificate[] certs, String authType) ???????????????throws java.security.cert.CertificateException { ???????????return; ???????} ???} ???????/** ????* 发送报文 ????* ?????* 通信失败时返回分两种:一种是抛异常,一种是返回"",本方法取前者 ????* ?????* @param requestData ????* ???????????请求报文 ????* @param headMap ????* ???????????head请求头参数 conn.setRequestProperty(key,value) ????* @param urlStr ????* ???????????请求地址 ????* @param sendEncoding ????* ???????????请求编码 ????* @param recvEncoding ????* ???????????返回编码 ????* @param connectionTimeout ????* ???????????链接超时时间 1000代表 1秒 ????* @param readTimeout ????* ???????????读取超时时间 1000代表1秒 ????* @return ????* @throws IOException ????* @author 超神之巅 ????*/ ???public static String send(String requestData,Map<String,String> headMap, String urlStr, String sendEncoding, String recvEncoding, int connectionTimeout, int readTimeout,String contentType) throws Exception { ???????URL url = null; ???????HttpsURLConnection conn = null; ???????ByteArrayOutputStream byteOut = null; ???????BufferedReader readInfo = null; ???????StringBuilder retBuilder = new StringBuilder();// 这里用不着多线程安全的StringBuffer ???????OutputStream out = null; ???????String line = null; ???????StringBuilder reqDetailProcedure = new StringBuilder();// 这里用不着多线程安全的StringBuffer ???????Date startTime = new Date(); ???????reqDetailProcedure.append("请求时间:【" + DATE_FORMATER.format(startTime) + "】").append("\r\n"); ???????reqDetailProcedure.append("请求地址:【" + urlStr + "】").append("\r\n"); ???????reqDetailProcedure.append("真实请求方式及编码:【post " + sendEncoding + "】").append("\r\n"); ???????reqDetailProcedure.append("期望返回编码:【" + recvEncoding + "】").append("\r\n"); ???????reqDetailProcedure.append("请求超时时间:【" + readTimeout / 1000 + "s】").append("\r\n"); ???????reqDetailProcedure.append("请求报文:【" + requestData + "】").append("\r\n"); ???????try {// ???????????如有必要,给?后的参数加encode(xxx,"UTF-8"),不然目标系统可能收到的request.getParameter()是乱码// ???????????String arg = java.net.URLEncoder.encode("中国","UTF-8");// ???????????url = new URL(urlStr+"?deptname="+arg); ???????????????????????url = new URL(urlStr); ???????????????????????trustAllHttpsCertificates(); ???????????HttpsURLConnection.setDefaultHostnameVerifier(hv); ???????????????????????conn = (HttpsURLConnection) url.openConnection(); ???????????conn.setRequestMethod("POST"); ???????????// 新增部分 ???????????//conn.setHostnameVerifier(new TrustAnyHostnameVerifier()); ???????????conn.setRequestProperty("SOAPAction", "\"\""); ???????????conn.setRequestProperty("Accept", "application/xml, application/json,application/dime, multipart/related, text/*"); ???????????// 如果没有下面这一行代码,服务器端可以通过request.getParameter()和request.getInputStream()都接收到相同信息 ???????????// Content-Type相关知识链接: http://www.cnblogs.com/whatlonelytear/p/6187575.html ???????????// conn如果不设Content-Type,则默认成application/x-www-form-urlencoded ???????????// 当然也可以配置成application/x-www-form-urlencoded;charset=UTF-8,此时要求服务端返回UTF-8编码,如果本地还用gbk去解码,有可能得到乱码 ???????????conn.setRequestProperty("Content-Type", contentType); ???????????// 如果把Content-Type的类型改变成非application/x-www-form-urlencoded,如改成text/xml, ???????????// 则目标服务器端仅能通过request.getInputStream()接收信息, 如conn.setRequestProperty("Content-Type", "text/xml;charset=GBK"); ???????????// Content-Type各类型解释: http://blog.csdn.net/blueheart20/article/details/45174399 ???????????????????????// conn.setRequestProperty("Accept-Charset", "utf-8");//未知 ???????????????????????//Cache-Control说明链接:http://huangyunbin.iteye.com/blog/1943310 ?或 http://www.cnblogs.com/whatlonelytear/articles/6385390.html ???????????conn.setRequestProperty("Cache-Control", "no-cache"); ???????????????????????//设置head头,如果已存在,则覆盖之前的head配置 ???????????if(headMap != null){ ???????????????for(Map.Entry<String, String > entry : headMap.entrySet()){ ???????????????????conn.setRequestProperty(entry.getKey(),entry.getValue()); ???????????????} ???????????????????????????} ???????????????????????// conn.setRequestProperty("appName", appName);//各系统需要设置应用系统名,如电销为telesales(无意义,本人自定义) ???????????conn.setUseCaches(false); // 忽略缓存 ???????????// get请求用不到conn.getOutputStream(),因为参数直接追加在地址后面,因此默认是false. ???????????// post请求(比如:文件上传)需要往服务区传输大量的数据,这些数据是放在http的body里面的,因此需要在建立连接以后,往服务端写数据. ???????????// 因为总是使用conn.getInputStream()获取服务端的响应,因此默认值是true. ???????????conn.setDoOutput(true); // 使用 URL ???????????????????????????????????// 连接进行输出,允许使用conn.getOutputStream().write() ???????????conn.setDoInput(true); // 使用 URL ???????????????????????????????????// 连接进行输入,允许使用conn.getInputStream().read(); ???????????conn.setConnectTimeout(connectionTimeout);// 链接超时 ???????????conn.setReadTimeout(readTimeout);// 读取超时 ???????????conn.connect();// 建立链接 ???????????byteOut = new ByteArrayOutputStream(); ???????????byteOut.write(requestData.getBytes(sendEncoding));// 以指定编码发送,如果有乱码,修改之 ???????????byte[] buf = byteOut.toByteArray(); ???????????out = conn.getOutputStream(); ???????????out.write(buf); ???????????out.flush(); ???????????reqDetailProcedure.append("响应码和状态:【" + conn.getResponseCode() + "/" + conn.getResponseMessage() + "】").append("\r\n"); ???????????if (HttpURLConnection.HTTP_OK == conn.getResponseCode()) {// 正确返回 ???????????????InputStream tempStream = conn.getInputStream(); ???????????????readInfo = new BufferedReader(new java.io.InputStreamReader(tempStream, recvEncoding));// 以指定编码读取返回信息,如果有乱码,修改之 ???????????????while ((line = readInfo.readLine()) != null) { ???????????????????retBuilder.append(line).append(LINE_SEPARATOR); ???????????????} ???????????} else {// 没有正确返回 ???????????????// 这个else分支有冗余代码,一来代码不多,二来这个分支是经过长时间思考,还是保留了下来,方便我以后对错误做不抛异常处理等 ???????????????InputStream tempStream = conn.getInputStream();// 如果响应码不是200,一般在这里就开始报异常,不会走到下面几行中去的. ???????????????readInfo = new BufferedReader(new java.io.InputStreamReader(tempStream, recvEncoding));// cannotReach ???????????????while ((line = readInfo.readLine()) != null) {// cannotReach ???????????????????retBuilder.append(line);// cannotReach ???????????????}// cannotReach ???????????????reqDetailProcedure.append("@@返回异常报文:【" + retBuilder + "】").append("\r\n");// cannotReach ???????????} ???????} catch (IOException e) { ???????????e.printStackTrace(); ???????????throw e; ???????} finally { ???????????// 目标服务端用response.setContentType("text/html;charset=UTF-8");然后源调用方可以用conn.getContentType()获取到[猜测,暂未测试] ???????????// conn.getContentType()包含在Head返回的内容中. ???????????// 返回如果带编码,可以做成动态编码去把流转成字符串,暂不优化.这是极好的l优化点. ???????????reqDetailProcedure.append("返回内容类型及编码:【" + conn.getContentType() + "】").append("\r\n"); ???????????reqDetailProcedure.append("返回HEAD头信息:【" + conn.getHeaderFields() + "】").append("\r\n"); ???????????reqDetailProcedure.append("返回报文:【" + retBuilder.toString() + "】").append("\r\n"); ???????????Date endTime = new Date(); ???????????reqDetailProcedure.append("返回时间:【" + DATE_FORMATER.format(endTime) + "】").append("\r\n"); ???????????long diffMilliSecond = endTime.getTime() - startTime.getTime(); ???????????long diffSecond = (diffMilliSecond / 1000); ???????????reqDetailProcedure.append("耗时:【" + diffMilliSecond + "】毫秒,大约" + "【" + diffSecond + "】秒").append("\r\n"); ???????????System.out.println(reqDetailProcedure.toString()); ???????????//ThreadLocalListContainer.put(reqDetailProcedure.toString()); ???????????// ThreadLocalMapContainer.put(KingConstants.REQ_DETAIL_PROCEDURE,reqDetailProcedure.toString()) ???????????try { ???????????????if (readInfo != null) { ???????????????????readInfo.close(); ???????????????} ???????????????if (byteOut != null) { ???????????????????byteOut.close(); ???????????????} ???????????????if (out != null) { ???????????????????out.close(); ???????????????} ???????????????if (conn != null) { ???????????????????conn.disconnect(); ???????????????} ???????????} catch (Exception e) { ???????????????System.out.println("关闭链接出错!" + e.getMessage()); ???????????} ???????} ???????return retBuilder.toString(); ???} ???????/** ????* 发送报文 ????* ?????* 通信失败时返回分两种:一种是抛异常,一种是返回"",本方法取前者 ????* ?????* @param requestData ????* ???????????请求报文 ????* @param urlStr ????* ???????????请求地址 ????* @param sendEncoding ????* ???????????请求编码 ????* @param recvEncoding ????* ???????????返回编码 ????* @param connectionTimeout ????* ???????????链接超时时间 1000代表 1秒 ????* @param readTimeout ????* ???????????读取超时时间 1000代表1秒 ????* @return ????* @throws IOException ????* @author 超神之巅 ????*/ ???public static String send(String requestData, String urlStr, String sendEncoding, String recvEncoding, int connectionTimeout, int readTimeout) throws Exception { ???????boolean flag = isJson(requestData);//是否JSON ???????String contentType="application/soap+xml"; ???????if(flag) { ???????????contentType = "application/json"; ???????} ???????return send( requestData,null, urlStr, sendEncoding, recvEncoding, connectionTimeout, readTimeout,contentType); ???} ???/** ????* ?????* @param filePath ????* ???????????文件绝对路径 ????* @param encoding ????* ???????????读取文件的编码 ????* @return ????* @author 超神之巅 ????* @throws Exception ????*/ ???public static String readStringFromFile(String filePath, String encoding) { ???????File file = new File(filePath); ???????// System.out.println("文件 "+filePath+"存在与否?: "+ file.exists()); ???????String tempLine = null; ???????String retStr = ""; ???????InputStreamReader isr = null;// way1: ???????// FileReader fr = null;//way2 ???????StringBuilder sb = new StringBuilder(); ???????try { ???????????if (file.exists()) { ???????????????isr = new InputStreamReader(new FileInputStream(file), encoding);// way1: ???????????????// fr = new FileReader(file);//way2 ???????????????BufferedReader br = new BufferedReader(isr);// way1: ???????????????// BufferedReader br = new BufferedReader(fr);;//way2: ???????????????tempLine = br.readLine(); ???????????????while (tempLine != null) { ???????????????????sb.append(tempLine).append(System.getProperty("line.separator")); ???????????????????tempLine = br.readLine(); ???????????????} ???????????????retStr = sb.toString(); ???????????} ???????} catch (UnsupportedEncodingException e) { ???????????e.printStackTrace(); ???????} catch (FileNotFoundException e) { ???????????e.printStackTrace(); ???????} catch (IOException e) { ???????????e.printStackTrace(); ???????} finally { ???????????try { ???????????????if (isr != null) ???????????????????isr.close(); ???????????} catch (Exception e) { ???????????????e.printStackTrace(); ???????????} ???????} ???????// System.out.println("读到的文件内容如下:"); ???????// System.out.println(retStr); ???????return retStr; ???} ???/** ????* 判断字符串是否为JSON格式 ????* @param str ????* @return ????*/ ???public static boolean isJson(String str){ ???????if (StringUtils.isBlank(str)) { ???????????return false; ???????} ???????????????boolean flag1 = (str.startsWith("{") && str.endsWith("}")); ???????boolean flag2 = (str.startsWith("[") && str.endsWith("]")); ???????????????return (flag1 || flag2); ???} ???/*public static final void writeInfo(HttpServletResponse resp, String errorCode, String respInfo, Map<String, Object> map) { ???????map.put("errorCode", errorCode); ???????map.put("respInfo", respInfo); ???????String detail = ThreadLocalListContainer.getAll(); ???????map.put(KingConstants.DETAIL_PROCEDURE, detail); ???????ThreadLocalListContainer.clearAll(); ???????// map.put(KingConstants.DETAIL_PROCEDURE, detail); ???????try {// ???????????String gsonInfo = new Gson().toJson(map);//old ???????????Gson gson = new GsonBuilder().setPrettyPrinting().create();//new ???????????String gsonInfo = gson.toJson(map); ???????????PrintWriter pw = resp.getWriter(); ???????????pw.print(gsonInfo); ???????????pw.flush(); ???????????pw.close(); ???????} catch (IOException e) { ???????????e.printStackTrace(); ???????} ???}*/ ???/** ????* ?????* @param resp ????* @param errorCode ????* @param respInfo ????* @param map ????* ...... ????* @time 2017年4月23日 上午9:12:43 ????* @author 超神之巅 ????*/ ???/*public static final void writeInfo(HttpServletResponse resp, KingResp result) { ???????String detail = ThreadLocalListContainer.getAll(); ???????result.setDetailProcedure(detail); ???????ThreadLocalListContainer.clearAll(); ???????try {// ???????????String gsonInfo = new Gson().toJson(map);//old ???????????Gson gson = new GsonBuilder().setPrettyPrinting().create();//new ???????????String gsonInfo = gson.toJson(result); ???????????FileTool.writeStringToFile("d:/temp/myinfo.txt", gsonInfo, "gbk", false); ???????????PrintWriter pw = resp.getWriter(); ???????????pw.print(gsonInfo); ???????????pw.flush(); ???????????pw.close(); ???????} catch (IOException e) { ???????????e.printStackTrace(); ???????} ???}*/ ???????public static final void writeInfo(HttpServletResponse resp, String respInfo) { ???????try { ???????????PrintWriter pw = resp.getWriter(); ???????????pw.print(respInfo); ???????????pw.flush(); ???????????pw.close(); ???????} catch (IOException e) { ???????????e.printStackTrace(); ???????} ???} ???????public static final SimpleDateFormat DATE_FORMATER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:sss"); ???public static void main(String[] args) throws Exception { ???????String requestUrl ?= "https://bx.zhcgs.gov.cn:8060/NewBxInfo/BxInfo.asmx"; ???????//把cacerts20181015文到该目录 ???????System.setProperty("javax.net.ssl.trustStore", ???????????????"K:\\myprogram\\jdk\\jdk8\\jdk1.8.0_141\\jre\\lib\\security\\cacerts20181015"); ???????String requestData = readStringFromFile("d:/file/send.xml", "UTF-8");// 有乱码,请修改指定编码 ???????String sencXml = HttpsTool.send(requestData, requestUrl, "utf-8", "utf-8", 300 * 1000, 300 * 1000);// 大家最终只要使用这一句代码就可调用 ???}}
https请求之绕过证书安全校验工具类(原)
原文地址:https://www.cnblogs.com/hmhhz/p/10177901.html