java https tlsv1_https请求绕过TLSv1协议的工具类【调整】

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.security.cert.CertificateException;

import java.security.cert.X509Certificate;

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.SSLContext;

import javax.net.ssl.SSLSession;

import javax.net.ssl.TrustManager;

import javax.net.ssl.X509TrustManager;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;

/**

* http post发送工具

*

* @author King

*

*/

public class WCHttpsTool {

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());

}

private static class TrustAnyTrustManager implements X509TrustManager {

@Override

public void checkClientTrusted(X509Certificate[] chain, String authType)

throws CertificateException {

}

@Override

public void checkServerTrusted(X509Certificate[] chain, String authType)

throws CertificateException {

}

@Override

public X509Certificate[] getAcceptedIssuers() {

return null;

}

}

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 King

*/

@SuppressWarnings("null")

public static String send(String requestData,Map 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);

System.setProperty("https.protocols", "TLSv1");

SSLContext sc = SSLContext.getInstance("TLSv1");

sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom());

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 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 King

*/

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 King 金剑波

* @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 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 King

*/

/*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);// 大家最终只要使用这一句代码就可调用

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值