之前与某运营商渠道对接口,对方弄了一个https双向认证,项目非常着急,当时我对https一点概念都没有。
现在平安度过项目预运营期,特来总结。
首先什么是https,所谓Https说白了,就是加密,单向Https是,客户端保存着服务端的证书并信任该证书即可,而双向Https认证就麻烦了,服务器要存你的证书,你也要存服务器的证书。说白了这些都是概念,我们做软件开发的,如果有业余时间可以去研究研究,但实际上业务对接时间都非常紧
出这篇文章的目的在于,百度 + Google我都没有发现特别好的方案,要不就是很老的实现方式。虽然有部分可以用,但很多接口和实现都已经被弃用。未来可能被删除。
以下是我实现的方式,请各位大佬检验:
如果有着急的朋友,可以直接拿这份代码拷贝到你项目中,这是一个独立的工具类,依赖apache httpclient,应该就没有其他的了
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
</dependency>
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import javax.net.ssl.HostnameVerifier;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import javax.net.ssl.SSLContext;
import java.io.*;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
/**
* Created with IntelliJ IDEA.
*
* @Author: eddie
* @Date: 2018-09-27
*/
public class HttpsClientUtil {
/**
* 获取文件流
* HttpsClientUtil.class.getClassLoader().getResource("cert/clients.jks").getFile()
*/
private static final StringTRUST_STORE_FILE ="";
public static StringHttpsPostRequest(String requestUrl,String requestBody, String charset)throws Exception{
StringBuffer resultsb =null;
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(initConfig()).build();
try {
HttpPost httpPost =new HttpPost(requestUrl);
httpPost.addHeader("timestamp", "");
StringEntity stringEntity =new StringEntity(requestBody, Charset.forName(charset));
stringEntity.setContentType("application/json");
httpPost.setEntity(stringEntity);
CloseableHttpResponse response = httpClient.execute(httpPost);
resultsb =send(response);
}finally {
httpClient.close();
}
return resultsb ==null ?null : resultsb.toString();
}
public static StringHttpsGetRequest(String requestUrl, Map paramMap)throws Exception{
StringBuffer resultsb =null;
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(initConfig()).build();
try {
StringBuffer url =new StringBuffer().append(requestUrl);
for (String key : paramMap.keySet()){
}
HttpGet httpGet =new HttpGet(requestUrl);
CloseableHttpResponse response = httpClient.execute(httpGet);
resultsb =send(response);
}finally {
httpClient.close();
}
return resultsb ==null ?null : resultsb.toString();
}
public static StringHttpGetRequest(String requestUrl)throws Exception{
StringBuffer resultsb =null;
CloseableHttpClient httpClient =getHttpClient();
try {
HttpGet httpGet =new HttpGet(requestUrl);
httpGet.addHeader("Content-Type", "application/json;encoding=utf-8");
CloseableHttpResponse response = httpClient.execute(httpGet);
resultsb =send(response);
}finally {
httpClient.close();
}
return resultsb ==null ?null : resultsb.toString();
}
private static StringBuffersend(CloseableHttpResponse response)throws IOException {
try {
StringBuffer resultsb =null;
HttpEntity entity = response.getEntity();
if (entity !=null) {
resultsb =new StringBuffer();
BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(entity.getContent(),"UTF-8"));
String text;
while ((text = bufferedReader.readLine()) !=null) {
resultsb.append(text);
}
}
EntityUtils.consume(entity);
return resultsb;
}finally {
response.close();
}
}
private static SSLConnectionSocketFactoryinitConfig()throws Exception {
KeyStore keyStore = KeyStore.getInstance("jks");
InputStream in =null;
try {
in =new FileInputStream(TRUST_STORE_FILE);
keyStore.load(in, "bld365".toCharArray());
SSLContext sslcontext = SSLContexts.custom()
.loadTrustMaterial(keyStore, new TrustSelfSignedStrategy())
.loadKeyMaterial(keyStore, "bld365".toCharArray())
.build();
HostnameVerifier verifier = (s, sslSession) ->true;
return new SSLConnectionSocketFactory(
sslcontext,
new String[]{"TLSv1", "TLSv1.1", "TLSv1.2"},
null,
verifier
);
}catch (Exception e) {
e.printStackTrace();
throw new Exception("初始化client keyStore 失败:" + e.getMessage());
}finally {
if (null != in) {
in.close();
}
}
}
private static CloseableHttpClientgetHttpClient() {
RegistryBuilder registryBuilder = RegistryBuilder.create();
ConnectionSocketFactory plainSF =new PlainConnectionSocketFactory();
registryBuilder.register("http", plainSF);
//指定信任密钥存储对象和连接套接字工厂
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
TrustStrategy anyTrustStrategy = (x509Certificates, s) ->true;
HostnameVerifier verifier = (s, sslSession) ->true;
SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(trustStore, anyTrustStrategy).build();
LayeredConnectionSocketFactory sslSF =new SSLConnectionSocketFactory(sslContext, verifier);
registryBuilder.register("https", sslSF);
}catch (KeyStoreException e) {
throw new RuntimeException(e);
}catch (KeyManagementException e) {
throw new RuntimeException(e);
}catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
Registry registry = registryBuilder.build();
//设置连接管理器
PoolingHttpClientConnectionManager connManager =new PoolingHttpClientConnectionManager(registry);
return HttpClientBuilder.create().setConnectionManager(connManager).build();
}
}