最近项目涉及到的web-service接口,是https的,所以开发部署完实现个demo测试。但是在写demo的时候遇到些小问题,mark下,以后不要再走弯路,希望能帮助遇到同样问题的朋友。
1、证书相关问题。生成keystore: {jkd-path}/bin中有一个keytool,通过命令生成xxx.keystrore
keytool -genkey -keyalg RSA -validity 2000 -keystore xxx.keystrore按照提示完成生成过程:
具体参数含义如下图:
现在只是生成了一个存放证书的"库",我们需要把访问的server端的证书导入到我们刚才创建的"库"中。 (具体每个浏览器导出证书的过程类似) Chrome 导出证书过程:
具体导出的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的阶段.... 加油,共同进步~。