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单项连接,向服务端发送数据!");

}

}

单项认证时,只需要设置客户端信任的证书库就行。但是当是双向认证时,还需要设置客户端密钥库密码。

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双项连接,向服务端发送数据!");

}

}

下面来说说可能会遇到的异常:

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 ,表示成功。

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐