转载自:http://zhuyuehua.iteye.com/blog/1122444
https一般来说有单项SSL和双向SSL连接之分。
单项SSL连接,也就是只是客户端验证服务器证书。tomcat中clientAuth="false"的时候
代码如下:
- 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://。。。/。。_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单项连接,向服务端发送数据!");
- }
- }
单项认证时,只需要设置客户端信任的证书库就行。但是当是双向认证时,还需要设置客户端密钥库密码。
代码如下:
- 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://。。。/。。。_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 ,表示成功。
转载自:http://zhuyuehua.iteye.com/blog/1122444