`
liulanghan110
  • 浏览: 1063947 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

客户端如何向https服务器发送数据

    博客分类:
  • JAVA
 
阅读更多

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

 

 

 

分享到:
评论
2 楼 liulanghan110 2012-09-24  
stevenjohn 写道
写的不错,这几天正好自己公司再用HTTPS,我做了https的双向验证,找了好久,终于找到一个能请求https服务的代码。


楼主好人,楼主辛苦了,楼主一生平安

我之前做的时候也是摸索了好久,资料不太好找。
1 楼 stevenjohn 2012-09-23  
写的不错,这几天正好自己公司再用HTTPS,我做了https的双向验证,找了好久,终于找到一个能请求https服务的代码。


楼主好人,楼主辛苦了,楼主一生平安

相关推荐

Global site tag (gtag.js) - Google Analytics