https一般來說有單項SSL和雙向SSL連接之分。
單項SSL連接,也就是只是客戶端驗證服務器證書。tomcat中clientAuth="false"的時候,HTTPS單向驗證如下:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.util.Date;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class ClientSendData {
static Log log = LogFactory.getLog(ClientSendData.class);
// 客戶端信任的證書
private String sslTrustStore;
private String sslTrustStorePassword;
private String Url;
//初始化數據
public ClientSendData() {
sslTrustStore = "D:/ssl/clientTrust.jks";
sslTrustStorePassword = "123456";
Url = "https://test.yihaodian.com:8443/ims/feedbackToPingAn_getData.action";
}
public String sendData(String data) {
String receivedData = null;
try {
//設置系統參數
System.setProperty("javax.net.ssl.trustStore", sslTrustStore);
System.setProperty("javax.net.ssl.trustStorePassword",
sslTrustStorePassword);
receivedData = send(Url, data);
} catch (Exception e) {
e.printStackTrace();
}
return receivedData;
}
public static String send(String sendurl, String sendData)
throws Exception {
URL url = new URL(sendurl);
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
return true;
}
};
System.setProperty("java.protocol.handler.pkgs","sun.net.www.protocol");
HttpsURLConnection.setDefaultHostnameVerifier(hv);
Date current = new Date(System.currentTimeMillis());
log.info("begint to open connection at " + current);
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
Date end = new Date(System.currentTimeMillis());
log.info("open connection ok at " + end + ",cost:"+ (end.getTime() - current.getTime()));
connection.setRequestProperty("Content-Type", "text/xml");
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestMethod("POST");
connection.setUseCaches(false);
connection.setReadTimeout(30000);
byte data[] = sendData.getBytes();
current = new Date(System.currentTimeMillis());
log.info("[SSLIX]notifyEai,begint to write data at " + current);
OutputStream out = connection.getOutputStream();
out.write(data);
end = new Date(System.currentTimeMillis());
log.info("write data ok at " + end + ",cost:"
+ (end.getTime() - current.getTime()));
StringBuffer receivedData = new StringBuffer();
current = new Date(System.currentTimeMillis());
log.info("begint to read data at " + current);
InputStreamReader inReader = new InputStreamReader(connection
.getInputStream(), "UTF-8");
BufferedReader aReader = new BufferedReader(inReader);
String aLine;
while ((aLine = aReader.readLine()) != null) {
receivedData.append(aLine);
}
end = new Date(System.currentTimeMillis());
log.info("read data ok at " + end + ",cost:"
+ (end.getTime() - current.getTime()));
log.info("開始返回狀態碼");
Integer statusCode = connection.getResponseCode();
log.info("返回狀態碼:" + statusCode);
aReader.close();
connection.disconnect();
return receivedData.toString();
}
public static void main(String[] args) {
ClientSendData t = new ClientSendData();
t.sendData("測試SSL單項連接,向服務端發送數據!");
}
}
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.util.Date;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class ClientSendData {
static Log log = LogFactory.getLog(ClientSendData.class);
// 客戶端信任的證書
private String sslTrustStore;
private String sslTrustStorePassword;
private String Url;
//初始化數據
public ClientSendData() {
sslTrustStore = "D:/ssl/clientTrust.jks";
sslTrustStorePassword = "123456";
Url = "https://test.yihaodian.com:8443/ims/feedbackToPingAn_getData.action";
}
public String sendData(String data) {
String receivedData = null;
try {
//設置系統參數
System.setProperty("javax.net.ssl.trustStore", sslTrustStore);
System.setProperty("javax.net.ssl.trustStorePassword",
sslTrustStorePassword);
receivedData = send(Url, data);
} catch (Exception e) {
e.printStackTrace();
}
return receivedData;
}
public static String send(String sendurl, String sendData)
throws Exception {
URL url = new URL(sendurl);
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
return true;
}
};
System.setProperty("java.protocol.handler.pkgs","sun.net.www.protocol");
HttpsURLConnection.setDefaultHostnameVerifier(hv);
Date current = new Date(System.currentTimeMillis());
log.info("begint to open connection at " + current);
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
Date end = new Date(System.currentTimeMillis());
log.info("open connection ok at " + end + ",cost:"+ (end.getTime() - current.getTime()));
connection.setRequestProperty("Content-Type", "text/xml");
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestMethod("POST");
connection.setUseCaches(false);
connection.setReadTimeout(30000);
byte data[] = sendData.getBytes();
current = new Date(System.currentTimeMillis());
log.info("[SSLIX]notifyEai,begint to write data at " + current);
OutputStream out = connection.getOutputStream();
out.write(data);
end = new Date(System.currentTimeMillis());
log.info("write data ok at " + end + ",cost:"
+ (end.getTime() - current.getTime()));
StringBuffer receivedData = new StringBuffer();
current = new Date(System.currentTimeMillis());
log.info("begint to read data at " + current);
InputStreamReader inReader = new InputStreamReader(connection
.getInputStream(), "UTF-8");
BufferedReader aReader = new BufferedReader(inReader);
String aLine;
while ((aLine = aReader.readLine()) != null) {
receivedData.append(aLine);
}
end = new Date(System.currentTimeMillis());
log.info("read data ok at " + end + ",cost:"
+ (end.getTime() - current.getTime()));
log.info("開始返回狀態碼");
Integer statusCode = connection.getResponseCode();
log.info("返回狀態碼:" + statusCode);
aReader.close();
connection.disconnect();
return receivedData.toString();
}
public static void main(String[] args) {
ClientSendData t = new ClientSendData();
t.sendData("測試SSL單項連接,向服務端發送數據!");
}
}
單項認證時,只需要設置客戶端信任的證書庫就行。但是當是雙向認證時,還需要設置客戶端密鑰庫密碼。
HTTPS雙向驗證代碼如下:
public class ClientSendData {
static Log log = LogFactory.getLog(EaiChannel.class);
//客戶端密鑰庫
private String sslKeyStorePath;
private String sslKeyStorePassword;
private String sslKeyStoreType;
// 客戶端信任的證書
private String sslTrustStore;
private String sslTrustStorePassword;
private String eaiUrl;
//初始化數據
public ClientSendData() {
sslKeyStorePath = "D:/ssl/clientKeys.jks";
sslKeyStorePassword = "123456";
sslKeyStoreType = "JKS"; //密鑰庫類型,有JKS PKCS12等
sslTrustStore = "D:/ssl/clientTrust.jks";
sslTrustStorePassword = "123456";
eaiUrl = "https://test.yihaodian.com:8443/ims/feedbackToPingAn_getData.action";
}
public String sendData(String data) {
String receivedData = null;
try {
System.setProperty("javax.net.ssl.keyStore", sslKeyStorePath);
System.setProperty("javax.net.ssl.keyStorePassword",sslKeyStorePassword);
System.setProperty("javax.net.ssl.keyStoreType", sslKeyStoreType);
//設置系統參數
System.setProperty("javax.net.ssl.trustStore", sslTrustStore);
System.setProperty("javax.net.ssl.trustStorePassword",
sslTrustStorePassword);
receivedData = send(eaiUrl, data);
} catch (Exception e) {
e.printStackTrace();
}
return receivedData;
}
public static String send(String sendurl, String sendData)
throws Exception {
//和上面一樣
}
public static void main(String[] args) {
ClientSendData t = new ClientSendData();
t.sendData("測試SSL雙項連接,向服務端發送數據!");
}
}
static Log log = LogFactory.getLog(EaiChannel.class);
//客戶端密鑰庫
private String sslKeyStorePath;
private String sslKeyStorePassword;
private String sslKeyStoreType;
// 客戶端信任的證書
private String sslTrustStore;
private String sslTrustStorePassword;
private String eaiUrl;
//初始化數據
public ClientSendData() {
sslKeyStorePath = "D:/ssl/clientKeys.jks";
sslKeyStorePassword = "123456";
sslKeyStoreType = "JKS"; //密鑰庫類型,有JKS PKCS12等
sslTrustStore = "D:/ssl/clientTrust.jks";
sslTrustStorePassword = "123456";
eaiUrl = "https://test.yihaodian.com:8443/ims/feedbackToPingAn_getData.action";
}
public String sendData(String data) {
String receivedData = null;
try {
System.setProperty("javax.net.ssl.keyStore", sslKeyStorePath);
System.setProperty("javax.net.ssl.keyStorePassword",sslKeyStorePassword);
System.setProperty("javax.net.ssl.keyStoreType", sslKeyStoreType);
//設置系統參數
System.setProperty("javax.net.ssl.trustStore", sslTrustStore);
System.setProperty("javax.net.ssl.trustStorePassword",
sslTrustStorePassword);
receivedData = send(eaiUrl, data);
} catch (Exception e) {
e.printStackTrace();
}
return receivedData;
}
public static String send(String sendurl, String sendData)
throws Exception {
//和上面一樣
}
public static void main(String[] args) {
ClientSendData t = new ClientSendData();
t.sendData("測試SSL雙項連接,向服務端發送數據!");
}
}
下面來說說可能會遇到的異常:
1. java.security.NoSuchAlgorithmException
一般來說是密鑰庫類型不對,如上面的sslKeyStoreType = "JKS" 卻寫成PKCS12。
也有可能是證書的問題。
2. java.net.UnknownHostException
服務端地址不對。
3.java.net.SocketException: Unexpected end of file from server
這個異常和客戶端沒有關系,說明已經發送成功。是服務端的問題。有可能是防火墻的原因,也可能是服務端沒處理客戶端的響應。
另外有人說當URL過長時也會發生此錯誤,當使用URL發送數據時,可以參考此意見。
4.java.io.IOException:server returned HTTP response code :500
這個異常是服務端代碼的問題。服務端相應代碼執行時拋出了異常。
最后 如果返回的狀態碼是200 ,表示成功。