最近在与服务端联调https的时候,服务端返回:unexpected end of file from server
1.最开始使用httpRequest方法,返回unexpected end of file from server;
2.将HttpURLConnection 替换为HttpsURLConnection ,方法名改为httpsRequest,此时,代码中没有HttpURLConnection的使用;服务端返回正常;
3.由于http访问的需要,增加httpsRequest方法(使用HttpURLConnection类),此时,在使用httpsRequest方法访问https链接时,服务端返回unexpected end of file from server;
4.注释掉httpsRequest方法,服务端返回正常;
与以上接近玄学的解释不同,经过验证,确认为tomcat的JDK版本(8_131)对HttpsURLConnection 的支持有问题,改为8_172后,不再出现此问题。
package com.landicorp.platform.utils;
import com.landicorp.platform.common.ParamName;
import com.lwd.clusters.util.Logger;
import com.lwd.clusters.util.LoggerImpl;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.net.ssl.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.*;
import java.security.cert.CertificateException;
@Component("comon.utils.httputils")
public class HttpUtils {
private static Logger logger = new LoggerImpl();
private static SSLContext sslContext;
@Value("${server.config.ssl.keystore.password}")
private String keyStorePw;
@Value("${server.config.ssl.keystore.filepath}")
private String keyStoreFilePath;
@Value("${server.config.ssl.truststore.filepath}")
private String trustStoreFilePth;
@Value("${server.config.ssl.truststore.password}")
private String trustStorePw;
// public JSONObject httpRequest(String urlStr,JSONObject paramJsonObj){
// DataOutputStream bOutputStream = null;
// InputStream inputStream = null;
// JSONObject responseJson;
// String errorMsg;
// HttpURLConnection urlConnection = null;
// try {
// logger.info("url = "+ urlStr);
// logger.info("param = "+ paramJsonObj.toString());
// URL url = new URL(urlStr);
// urlConnection = (HttpURLConnection) url.openConnection();
//
// urlConnection.setDoInput(true);
// urlConnection.setDoOutput(true);
// urlConnection.setConnectTimeout(10*1000);
// //urlConnection.setReadTimeout(5*1000);
// urlConnection.setRequestMethod("POST");
// urlConnection.setRequestProperty("Connection", "close");
// urlConnection.setRequestProperty("Charset", "UTF-8");
// urlConnection.setRequestProperty("User-Agent", "directclient");
// urlConnection.setRequestProperty("Content-Type","application/json");
//
// bOutputStream = new DataOutputStream(urlConnection.getOutputStream());
// String paramStr = paramJsonObj.toString();
// bOutputStream.write(paramStr.getBytes("UTF-8"));
// bOutputStream.flush();
//
// logger.info("http response,ResponseMessage=" + urlConnection.getResponseCode() + "ResponseMessage=" + urlConnection.getResponseMessage());
//
// inputStream = urlConnection.getInputStream();
// StringBuffer responseSb = new StringBuffer();
// // 读取服务器数据
// if (inputStream != null) {
// ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
// int len = -1;
// byte[] buf = new byte[1024];
// while ((len = inputStream.read(buf)) != -1) {
// baOutputStream.write(buf, 0, len);
// }
// baOutputStream.flush();
// responseSb.append(baOutputStream.toString());
// }
// logger.info("http response,type=" + paramJsonObj.getString(ParamName.TYPE)
// + " jsonParam=" + responseSb);
// // 解析服务器返回数据
// responseJson = JSONObject.fromObject(responseSb.toString());
//
// return responseJson;
// } catch (Exception e) {
// logger.error(e,"Exception");
// e.printStackTrace();
// errorMsg = e.getMessage();
// } finally {
// if(urlConnection !=null){
// urlConnection.disconnect();
// urlConnection = null;
// }
// try {
// if(bOutputStream != null){
// bOutputStream.flush();
// bOutputStream.close();
// }
// if(inputStream != null)
// inputStream.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
// responseJson = new JSONObject();
// try {
// responseJson.put("error", errorMsg);
// } catch (JSONException e) {
// e.printStackTrace();
// }
// return responseJson;
// }
public JSONObject httpsRequest(String urlStr, JSONObject paramJsonObj) throws Exception {
trustAllHttpsCertificates();
DataOutputStream bOutputStream = null;
InputStream inputStream = null;
JSONObject responseJson;
String errorMsg;
HttpsURLConnection urlConnection = null;
try {
logger.info("url = "+ urlStr);
logger.info("param = "+ paramJsonObj.toString());
URL url = new URL(urlStr);
urlConnection = (HttpsURLConnection) url.openConnection();
// // 设置信任证书
// if(urlConnection instanceof HttpsURLConnection) {
// ((HttpsURLConnection) urlConnection)
// .setSSLSocketFactory(getSSLContext().getSocketFactory());
// }
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.setConnectTimeout(10*1000);
//urlConnection.setReadTimeout(5*1000);
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Connection", "close");
urlConnection.setRequestProperty("Charset", "UTF-8");
urlConnection.setRequestProperty("User-Agent", "directclient");
urlConnection.setRequestProperty("Content-Type","application/json");
bOutputStream = new DataOutputStream(urlConnection.getOutputStream());
String paramStr = paramJsonObj.toString();
bOutputStream.write(paramStr.getBytes("UTF-8"));
bOutputStream.flush();
logger.info("http response,ResponseMessage=" + urlConnection.getResponseCode() + "ResponseMessage=" + urlConnection.getResponseMessage());
inputStream = urlConnection.getInputStream();
StringBuffer responseSb = new StringBuffer();
// 读取服务器数据
if (inputStream != null) {
ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
int len = -1;
byte[] buf = new byte[1024];
while ((len = inputStream.read(buf)) != -1) {
baOutputStream.write(buf, 0, len);
}
baOutputStream.flush();
responseSb.append(baOutputStream.toString());
}
logger.info("http response,type=" + paramJsonObj.getString(ParamName.TYPE)
+ " jsonParam=" + responseSb);
// 解析服务器返回数据
responseJson = JSONObject.fromObject(responseSb.toString());
return responseJson;
} catch (Exception e) {
logger.error(e,"Exception");
e.printStackTrace();
errorMsg = e.getMessage();
} finally {
if(urlConnection !=null){
urlConnection.disconnect();
urlConnection = null;
}
try {
if(bOutputStream != null){
bOutputStream.flush();
bOutputStream.close();
}
if(inputStream != null)
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
responseJson = new JSONObject();
try {
responseJson.put("error", errorMsg);
} catch (JSONException e) {
e.printStackTrace();
}
return responseJson;
}
public SSLContext getSSLContext(){
if(sslContext==null){
try {
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(getkeyStore(),keyStorePw.toCharArray());
KeyManager[] keyManagers = kmf.getKeyManagers();
TrustManagerFactory trustManagerFactory=TrustManagerFactory.getInstance("SunX509");
trustManagerFactory.init(getTrustStore());
TrustManager[] trustManagers= trustManagerFactory.getTrustManagers();
sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagers, trustManagers, new SecureRandom());
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
}
return sslContext;
}
public KeyStore getkeyStore(){
KeyStore keySotre=null;
try {
keySotre = KeyStore.getInstance("PKCS12");
FileInputStream fis = new FileInputStream(new File(keyStoreFilePath));
keySotre.load(fis, keyStorePw.toCharArray());
fis.close();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return keySotre;
}
public KeyStore getTrustStore() throws IOException{
KeyStore trustKeyStore=null;
FileInputStream fis=null;
try {
trustKeyStore=KeyStore.getInstance("JKS");
fis = new FileInputStream(new File(trustStoreFilePth));
trustKeyStore.load(fis, trustStorePw.toCharArray());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
fis.close();
}
return trustKeyStore;
}
/**
* 从网络Url中下载文件
* @param urlStr
* @param savePath
* @throws IOException
*/
public void downLoadFromUrl(String urlStr,String savePath) throws Exception{
logger.info("start download :"+urlStr);
URL url = new URL(urlStr);
trustAllHttpsCertificates();
HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection();
// urlConnection.setDoInput(true);
// urlConnection.setDoOutput(false);
// urlConnection.setConnectTimeout(10*1000);
// urlConnection.setReadTimeout(10*1000);
urlConnection.setRequestMethod("GET");
// urlConnection.setRequestProperty("Connection", "close");
urlConnection.setRequestProperty("Charset", "UTF-8");
urlConnection.setRequestProperty("Content-Type","application/octet-stream");
//防止屏蔽程序抓取而返回403错误
//urlConnection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
int code = urlConnection.getResponseCode();
if (code != HttpURLConnection.HTTP_OK) {
throw new Exception("文件读取失败:"+code);
}
//conn.setRequestProperty("lfwywxqyh_token",toekn);
// // 设置信任证书
// if(urlConnection instanceof HttpsURLConnection) {
// ((HttpsURLConnection) urlConnection)
// .setSSLSocketFactory(getSSLContext().getSocketFactory());
// }
//得到输入流
InputStream inputStream = urlConnection.getInputStream();
File targetFile = new File(savePath);
if(!targetFile.getParentFile().exists()){
FileUtils.forceMkdir(targetFile.getParentFile());
}
//文件保存位置
FileOutputStream fos = new FileOutputStream(targetFile,false);
try {
byte[] buffer = new byte[1024 * 512];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
fos.flush();
}catch (IOException e){
e.printStackTrace();
if(inputStream != null)
inputStream.close();
if(fos != null){
fos.flush();
fos.close();
}
}
}
public void trustAllHttpsCertificates() throws Exception {
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
//logger.info("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost());
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(hv);
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, new java.security.SecureRandom());
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;
}
}
}