httpclient 发送https

    最近项目涉及到的web-service接口,是https的,所以开发部署完实现个demo测试。但是在写demo的时候遇到些小问题,mark下,以后不要再走弯路,希望能帮助遇到同样问题的朋友。

    1、证书相关问题。
生成keystore: {jkd-path}/bin中有一个keytool,通过命令生成xxx.keystrore

keytool -genkey  -keyalg RSA -validity 2000 -keystore xxx.keystrore

按照提示完成生成过程:
httpclient 发送https_第1张图片

具体参数含义如下图:
httpclient 发送https_第2张图片

现在只是生成了一个存放证书的"库",我们需要把访问的server端的证书导入到我们刚才创建的"库"中。
(具体每个浏览器导出证书的过程类似)
Chrome 导出证书过程:
httpclient 发送https_第3张图片
具体导出的cer方式应该都是可以的,我是默认导出第一个格式的。这里需要注意的是,导出的这个证书域名很重要,这个要与你代码里的域名保持一致,否则会提示域名不匹配导致请求被拒绝。

现在我们需要将导出的证书导入到我们刚才生成的xxx.keystore中,命令如下

keytool -importcert -trustcacerts -file zzz.cer -kestore xxx.keystore
其中-zzz.cer 就是你刚才导出证书的文件名。
其中-xxx.keystore就是你刚才生成的"库"。

    2、java代码实现

/**
 * 
 */
package demo.test;

import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

/**
 * @author Hero_Q
 * 
 */
public class HTTPSDemo {

	private static final String SERVER = "https://xxx.com";

	public static void main(String[] args) {
		HttpClient httpClient = new DefaultHttpClient();
		try {
			KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
			InputStream in = HTTPSDemo.class.getResourceAsStream("xxx.keystore");
			trustStore.load(in, "123456".toCharArray());
			in.close();
			SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
			Scheme sch = new Scheme("https", 443, socketFactory);
			httpClient.getConnectionManager().getSchemeRegistry().register(sch);

			HttpPost httpPost = new HttpPost(SERVER);
			System.out.println("executing request" + httpPost.getRequestLine());
			// 执行请求
			HttpResponse response = httpClient.execute(httpPost);// 获得响应实体
			HttpEntity entity = response.getEntity();

			System.out.println("----------------------------------------");
			System.out.println(response.getStatusLine());
			System.out.println(entity);
			if (entity != null) {
				System.out.println("Response content length: " + entity.getContentLength());
			}
			// 销毁实体
			EntityUtils.consume(entity);
		} catch (IOException | KeyStoreException | NoSuchAlgorithmException | CertificateException | KeyManagementException | UnrecoverableKeyException e) {
			e.printStackTrace();
		} finally {
			// 当不再需要HttpClient实例时,关闭连接管理器以确保释放所有占用的系统资源
			httpClient.getConnectionManager().shutdown();
		}
	}

}
(我用的是java7),代码中需要指定的文件路径就是刚才生成的xxx.keystore库,具体原理就是构造请求,注册https协议,加载keystore,发送请求~我本地测试是可以通过的,具体的post请求中还需要加入具体的请求参数。不过最基本的还是http、https这些底层的东西应该清晰,要不仅仅的是把别人的代码copy下,跑通了,再次遇到类似的问题或许优化时会很无奈... 并且httpclient 发布的4.3的api还是有些改动的,如果不知道最基本的原理,永远只能停留在copy的阶段.... 加油,共同进步~。

你可能感兴趣的:(httpclient 发送https)