httpclient java cer_httpclient发送https并通过证书认证

一、服务端不强制使用证书认证

可以使用httpclient提供的方法,绕过证书认证

private final RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(TIMEOUT).setConnectTimeout(TIMEOUT).build();

private synchronized CloseableHttpClient getHttpsClient() {

if (null == httpsClient) {

PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();

// Increase max total connection to 200

cm.setMaxTotal(200);

// Increase default max connection per route to 20

cm.setDefaultMaxPerRoute(20);

//关闭空闲两分钟的连接

cm.closeIdleConnections(120, TimeUnit.SECONDS);

SSLConnectionSocketFactory sslCSF = null;

try {

SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build();

sslCSF = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

} catch (Exception e) {

log.error(e.getMessage(), e);

}

httpsClient = HttpClients.custom().setSSLSocketFactory(sslCSF).setConnectionManager(cm).setDefaultRequestConfig(requestConfig).build();

}

return httpsClient;

}

二、服务端强制使用证书认证

第一种方法,将导出的证书导入jdk中:

keytool -import -keystore d:\Java\jdk1.7.0_60\jre\lib\security\cacerts -file d:/cas/keys/mycas.crt -alias anyname其中:d:\Java\jdk1.7.0_60\jre\lib\security\cacerts为客户端JVM的密钥库位置

如果提示:

keytool error: java.io.IOException: Keystore was tampered with, or password was incorrect

那么输入密码:changeit

这是因为JDK安装后会默认创建一个密钥库,密码为:changeit

也可以删除d:\Java\jdk1.7.0_60\jre\lib\security\cacerts 再输入上述命令。

这时可以直接使用非ssl认证的httpclient:

/**

* @return CloseableHttpClient

* @throws

* @Description: 得到http client对象

*/

private synchronized CloseableHttpClient getHttpClient() {

if (null == httpClient) {

PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();

// Increase max total connection to 200

cm.setMaxTotal(200);

// Increase default max connection per route to 20

cm.setDefaultMaxPerRoute(30);

//关闭空闲两分钟的连接

cm.closeIdleConnections(120, TimeUnit.SECONDS);

httpClient = HttpClients.custom().setConnectionManager(cm).setDefaultRequestConfig(requestConfig).build();

}

return httpClient;

}

第二种方法,自己创建密钥库:

1、证书相关问题。

生成客户端证书库: {jdk-path}/bin中有一个keytool,通过命令生成xxx.keystrore

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

按照提示完成生成过程:

52211b6ff9df5848809bbf11736751d7.png

具体参数含义如下图:

7ce43544088e27faafb2216626e1608b.png

现在只是生成了一个存放证书的”库”,我们需要把访问的server端的客户端证书导入到我们刚才创建的”库”中。

(具体每个浏览器导出证书的过程类似)

Chrome 导出证书过程:

f46dd60e40cda8479f8225a30bef889f.png

4dd674a55364af867c2d2ff1c7f8e2dd.png

713eb033844ec2366535179f0978520f.png

具体导出的cer方式应该都是可以的,我是默认导出第一个格式的。这里需要注意的是,导出的这个证书域名很重要,这个要与你代码里的域名保持一致,否则会提示域名不匹配导致请求被拒绝。

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

keytool -importcert -trustcacerts -file zzz.cer -keystore xxx.keystore

其中-zzz.cer 就是你刚才导出证书的文件名。

其中-xxx.keystore就是你刚才生成的”库”。

2、java代码实现

import java.io.*;

import java.security.KeyStore;

import java.util.List;

import java.util.concurrent.Future;

import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLContext;

import com.ning.http.client.*;

import org.apache.commons.io.IOUtils;

import org.apache.http.HttpEntity;

import org.apache.http.HttpResponse;

import org.apache.http.NameValuePair;

import org.apache.http.client.ClientProtocolException;

import org.apache.http.client.HttpClient;

import org.apache.http.client.config.RequestConfig;

import org.apache.http.client.entity.UrlEncodedFormEntity;

import org.apache.http.client.methods.HttpGet;

import org.apache.http.client.methods.HttpPost;

import org.apache.http.conn.ssl.SSLConnectionSocketFactory;

import org.apache.http.conn.ssl.SSLContextBuilder;

import org.apache.http.conn.ssl.TrustSelfSignedStrategy;

import org.apache.http.entity.InputStreamEntity;

import org.apache.http.impl.client.CloseableHttpClient;

import org.apache.http.impl.client.HttpClients;

import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;

下面是创建httpclient的方法:

private final RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(TIMEOUT).setConnectTimeout(TIMEOUT).build();

/**

* 创建证书认证httpclient

* @param keystoreClassPath 证书路径

* @param certPassword 证书密钥

* @return

*/

private synchronized CloseableHttpClient getHttpsClientSSLAuth(String keystoreClassPath, String certPassword) {

if (null == httpsClientSSLAuth) {

PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();

// Increase max total connection to 200

cm.setMaxTotal(200);

// Increase default max connection per route to 20

cm.setDefaultMaxPerRoute(20);

//关闭空闲两分钟的连接

cm.closeIdleConnections(120, TimeUnit.SECONDS);

try {

KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());

//KeyStore trustStore = KeyStore.getInstance("PKCS12");

InputStream in = RequestServiceImpl.class.getResourceAsStream(keystoreClassPath);

trustStore.load(in, certPassword.toCharArray());

in.close();

SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()).build();

SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext);

httpsClientSSLAuth = HttpClients.custom().setSSLSocketFactory(socketFactory).setConnectionManager(cm).setDefaultRequestConfig(requestConfig).build();

} catch (Exception e) {

log.error(e.getMessage(), e);

}

}

return httpsClientSSLAuth;

}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值