在上篇文章《HttpClient配置ssl实现https简单示例——绕过证书验证》中简单分享了一下如何绕过证书验证。如果你想用httpclient访问一个网站,但是对方的证书没有通过ca认证或者其他问题导致证书不被信任,比如12306的证书就是这样的。所以对于这样的情况,你只能是选择绕过证书验证的方案了。
但是,如果是自己用jdk或者其他工具生成的证书,还是希望用其他方式认证自签名的证书,这篇文章就来分享一下如何设置信任自签名的证书。当然你也可以参考官网示例中。
要想信任自签名的证书,必须得知道密钥库的路径及密钥库的密码。然后加载到程序来才可以。具体代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
/**
* 设置信任自签名证书
*
* @param keyStorePath 密钥库路径
* @param keyStorepass 密钥库密码
* @return
*/
public
static
SSLContext custom(String keyStorePath, String keyStorepass){
SSLContext sc =
null
;
FileInputStream instream =
null
;
KeyStore trustStore =
null
;
try
{
trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
instream =
new
FileInputStream(
new
File(keyStorePath));
trustStore.load(instream, keyStorepass.toCharArray());
// 相信自己的CA和所有自签名的证书
sc = SSLContexts.custom().loadTrustMaterial(trustStore,
new
TrustSelfSignedStrategy()).build();
}
catch
(KeyStoreException | NoSuchAlgorithmException| CertificateException | IOException | KeyManagementException e) {
e.printStackTrace();
}
finally
{
try
{
instream.close();
}
catch
(IOException e) {
}
}
return
sc;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
/**
* 模拟请求
*
* @param url 资源地址
* @param map 参数列表
* @param encoding 编码
* @return
* @throws ParseException
* @throws IOException
* @throws KeyManagementException
* @throws NoSuchAlgorithmException
* @throws ClientProtocolException
*/
public
static
String send(String url, Map
throws
ClientProtocolException, IOException {
String body = ;
//tomcat是我自己的密钥库的密码,你可以替换成自己的
//如果密码为空,则用nopassword代替
SSLContext sslcontext = custom(D:\keys\wsriakey, tomcat);
// 设置协议http和https对应的处理socket链接工厂的对象
Registry
.register(http, PlainConnectionSocketFactory.INSTANCE)
.register(https,
new
SSLConnectionSocketFactory(sslcontext))
.build();
PoolingHttpClientConnectionManager connManager =
new
PoolingHttpClientConnectionManager(socketFactoryRegistry);
HttpClients.custom().setConnectionManager(connManager);
//创建自定义的httpclient对象
CloseableHttpClient client = HttpClients.custom().setConnectionManager(connManager).build();
// CloseableHttpClient client = HttpClients.createDefault();
//创建post方式请求对象
HttpPost httpPost =
new
HttpPost(url);
//装填参数
List
new
ArrayList
if
(map!=
null
){
for
(Entry
nvps.add(
new
BasicNameValuePair(entry.getKey(), entry.getValue()));
}
}
//设置参数到请求对象中
httpPost.setEntity(
new
UrlEncodedFormEntity(nvps, encoding));
System.out.println(请求地址:+url);
System.out.println(请求参数:+nvps.toString());
//设置header信息
//指定报文头【Content-type】、【User-Agent】
httpPost.setHeader(Content-type, application/x-www-form-urlencoded);
httpPost.setHeader(User-Agent, Mozilla/
4.0
(compatible; MSIE
5.0
; Windows NT; DigExt));
//执行请求操作,并拿到结果(同步阻塞)
CloseableHttpResponse response = client.execute(httpPost);
//获取结果实体
HttpEntity entity = response.getEntity();
if
(entity !=
null
) {
//按指定编码转换结果实体为String类型
body = EntityUtils.toString(entity, encoding);
}
EntityUtils.consume(entity);
//释放链接
response.close();
return
body;
}
|
1
2
3
4
5
6
7
8
9
10
11
|
public
static
void
main(String[] args)
throws
ParseException, IOException, KeyManagementException, NoSuchAlgorithmException{
String url = https:
//sso.tgb.com:8443/cas/login;
String body = send(url,
null
, utf-
8
);
System.out.println(交易响应结果长度:+body.length());
System.out.println(-----------------------------------);
url = https:
//kyfw.12306.cn/otn/;
body = send(url,
null
, utf-
8
);
System.out.println(交易响应结果长度:+body.length());
}
|
从结果中,我们很清楚的看到,使用自签名的证书,访问自签名的网站可以正常访问,访问12306则会失败。所以自签名的也只能用于自定义密钥和证书的情况下使用。而12306这种情况还是要用上一篇提到的“绕过证书验证”方案。
http://www.2cto.com/kf/201511/450707.html