httpclient-4.5.jar 定时发送http包,忽然有一天报错,http证书变更引起的。
之前的代码
try {
CloseableHttpClient httpClient = buildDefaultHttpClient();
String url = domain.getUrl();
HttpGet httpGet = new HttpGet(url);
httpGet.addHeader("User-Agent", NetUtil.INSPECTOR_USER_AGENT);
httpGet.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
httpGet.addHeader("Accept-Encoding", "gzip, deflate");
httpGet.addHeader("Accept-Language", "zh-CN,zh;q=0.9");
CloseableHttpResponse resp = httpClient.execute(httpGet);
String responseBody = EntityUtils.toString(resp.getEntity(), "utf-8");
respEnd = DateUtil.toEpochMilliseconds(LocalDateTime.now());
len = responseBody.length();
logger.info("http报文响应正文长度:{}B", len);
String extractedTitle = NetUtil.extractTitle(responseBody);
return builder.withRespEnd(respEnd).withRespLen(len)
.withHttpStatus((short) resp.getStatusLine().getStatusCode())
.withRetrieveTitle(extractedTitle)
.withTitleMatched(StringUtils.equals(domain.getTitle(), extractedTitle))
.build();
} catch (IOException e) {
}
之后的代码
try {
CloseableHttpClient httpClient = buildDefaultHttpClientTrustSSL();//信任证书
String url = domain.getUrl();
HttpGet httpGet = new HttpGet(url);
httpGet.addHeader("User-Agent", NetUtil.INSPECTOR_USER_AGENT);
httpGet.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
httpGet.addHeader("Accept-Encoding", "gzip, deflate");
httpGet.addHeader("Accept-Language", "zh-CN,zh;q=0.9");
CloseableHttpResponse resp = httpClient.execute(httpGet);
String responseBody = EntityUtils.toString(resp.getEntity(), "utf-8");
respEnd = DateUtil.toEpochMilliseconds(LocalDateTime.now());
len = responseBody.length();
logger.info("http报文响应正文长度:{}B", len);
String extractedTitle = NetUtil.extractTitle(responseBody);
return builder.withRespEnd(respEnd).withRespLen(len)
.withHttpStatus((short) resp.getStatusLine().getStatusCode())
.withRetrieveTitle(extractedTitle)
.withTitleMatched(StringUtils.equals(domain.getTitle(), extractedTitle))
.build();
} catch (IOException e) {
}
/**
* 信任SSL证书
* @return
*/
public static CloseableHttpClient buildDefaultHttpClientTrustSSL()
{
SSLContext sslContext = null;
try {
sslContext = SSLContextBuilder.create().useProtocol(SSLConnectionSocketFactory.SSL).loadTrustMaterial((x, y) -> true).build();
} catch (Exception e) {
e.printStackTrace();
}
RequestConfig config = RequestConfig.custom()
.setSocketTimeout(30000)
.setConnectTimeout(30000)
.setConnectionRequestTimeout(30000)
.setContentCompressionEnabled(true)
.build();
return HttpClientBuilder.create().setDefaultRequestConfig(config).setSSLContext(sslContext).setSSLHostnameVerifier((x, y) -> true).build();
}
public static CloseableHttpClient buildDefaultHttpClient()
{
RequestConfig defaultRequestConfig = RequestConfig.custom()
.setSocketTimeout(30000)
.setConnectTimeout(30000)
.setConnectionRequestTimeout(30000)
.setContentCompressionEnabled(true)
.setStaleConnectionCheckEnabled(true)
.build();
return HttpClients.custom().setDefaultRequestConfig(defaultRequestConfig).build();
}
例如:
我原来创建 httpClient 是这么写的:
CloseableHttpClient httpClient= HttpClients.custom().setDefaultRequestConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build()).build();
改之后:
CloseableHttpClient httpClient= buildDefaultHttpClientTrustSSL();
/**
* 信任SSL证书
* @return
*/
public static CloseableHttpClient buildDefaultHttpClientTrustSSL()
{
SSLContext sslContext = null;
try {
sslContext = SSLContextBuilder.create().useProtocol(SSLConnectionSocketFactory.SSL).loadTrustMaterial((x, y) -> true).build();
} catch (Exception e) {
e.printStackTrace();
}
RequestConfig config = RequestConfig.custom()
.setSocketTimeout(30000)
.setConnectTimeout(30000)
.setConnectionRequestTimeout(30000)
.setContentCompressionEnabled(true)
.setCookieSpec(CookieSpecs.STANDARD)
.build();
// return HttpClientBuilder.create().setDefaultRequestConfig(config).setSSLContext(sslContext).setSSLHostnameVerifier((x, y) -> true).build();
return HttpClients.custom().setDefaultRequestConfig(config).setSSLContext(sslContext).setSSLHostnameVerifier((x, y) -> true).build();
}
在要访问的https网站,F12,如图:
View certificate(蓝色部分)-- 导出证书
导入证书:
keytool -import -v -trustcacerts -alias taobao -file taobao.cer -storepass changeit -keystore %JAVA_HOME%/jre/lib/security/cacerts
解释说明:
1、taobao 是可以自己修改的名称, taobao.cer 是导出的证书,同样,这里的证书名字也是随便取的,但前提是保证将%JAVA_HOME%/jre/lib/security目录的cacerts文件内之前没有导入同名证书,就是要保证你将要导入的证书名称唯一性。
2、changeit 是密码, java默认的。
3、keytool是jdk中bin目录的一个exe文件,是jdk默认自带的,在我电脑的目录是:/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/bin/keytool.exe
4、%JAVA_HOME%/jre/lib/security/cacerts 这个路径中%JAVA_HOME%/jre/lib/security/是路径,cacerts是文件(即将要把证书导入到其中的文件)。当然要确保你已经配置过java_home环境变量,我的java_home环境变量为:/usr/lib/jvm/java-1.8.0-openjdk-amd64
5、其他保持不变。
6、如果提示:"是否信任此证书? [否]:" ,那么请输入"y"。
其实这个方法也是有效的