由于当时项目用的是http协议,然后要求说要改成https,所以遇到了一些问题,在此记录下。
1.第一个遇到的问题异常: java.security.cert.CertificateException:no name matching 网址 found。
由于https比http多了一些东西,其中就包括加密和证书的一些东西,所以当你在传输数据的时候,由于服务端的证书客户端无法信任,所以它无法获得证书从而无法连接。其实可以通过服务端那边配置解决,但是我在联调的时候那边是叫我到客服端解决,所以有了如下一些东西。。。
//解决https证书问题,使客户端相信所有证书
private static class TrustAnyTrustManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[] {};
}
}
private static class TrustAnyHostnameVerifier implements HostnameVerifier {
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
//在你要传输数据的类中加入如上两个私有的类,然后在配置connection属性时,按如下方式设置即可:
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(sc.getSocketFactory());
connection.setHostnameVerifier(new TrustAnyHostnameVerifier());
2.第二个就比较坑了,在用new ObjectOutputStream() 包裹connection.getOutputStream()后数据就发不过去,所以就直接用connection.getOutputStream()去写数据就好了,当时困扰我挺久的,后来慢慢试才发现是这个东西出了问题,不知道是不是就我一个人有问题,虽然不知道为什么这样会有问题,但是还是记录下,以后对这些东西有更深刻的认识再来完善吧:
/*ObjectOutputStream out = null;*/
OutputStream out = null;
BufferedReader inputStreamReader = null;
try {
SSLContext sc = SSLContext.getInstance("SSL","SunJSSE");
sc.init(null, new TrustManager[] { new TrustAnyTrustManager()},
new java.security.SecureRandom());
URL url = new URL(urls);
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(sc.getSocketFactory());
connection.setHostnameVerifier(new TrustAnyHostnameVerifier());
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setConnectTimeout(30000);
connection.setReadTimeout(30000);
connection.setInstanceFollowRedirects(true);
connection.setRequestMethod("POST"); // 设置请求方式
connection.setRequestProperty("Authorization", "Basic " + unamepwordbase64);
connection.setRequestProperty("Accept-Charset", "utf-8"); // 设置接收数据的格式
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); // 设置发送数据的格式
connection.connect();
/* out = new ObjectOutputStream(connection.getOutputStream()); // 此处不能用objectoutputstream会抛出500异常*/
out = connection.getOutputStream();
out.write(json.getBytes("UTF-8"));
out.flush();
out.close();
//获取响应
inputStreamReader = new BufferedReader(new InputStreamReader(connection.getInputStream(),"UTF-8"));
// 读取响应
StringBuffer buffer = new StringBuffer();
String data = new String("");
while ((data = inputStreamReader.readLine()) != null) {
buffer.append(data);
}
log.info(buffer.toString());
} catch (IOException | NoSuchAlgorithmException | NoSuchProviderException | KeyManagementException e) {
log.info(e.getMessage());
e.printStackTrace();
}catch (Exception e) {
log.info(e.getMessage());
e.printStackTrace();
}finally{
try {
if(inputStreamReader != null){
inputStreamReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
3.在此提醒一下https数据在发送的时候是在调用connection.getInputStream()的时候,而且发送过后此链接便不能再发送了,有点类似一次性消费的感觉,如果你想了解更多可以参考http://liuxi1024.iteye.com/blog/519047这篇博客写的挺详细的,但是我的第二个问题就是从他这产生的。。。。不知道他是不是能正常的传输。