从一滴水开始 的个人博客

纵有疾风起,人生不言弃

Open Source, Open Mind,
Open Sight, Open Future!
  menu
19 文章
8821 浏览
4 当前访客
ღゝ◡╹)ノ❤️

openssl获取服务端证书并导入到本地jdk证书库+忽略证书检测,解决'unable to find valid certification path to requested target'

在调用服务端接口时出现如下异常unable to find valid certification path to request target,从异常信息中可以看到错误是因为找不到证书导致的。解决方案有两个:

  • 正常的方案:当然是找到证书并安装证书。
  • 暴力的方案:取消证书认证,信任所有请求链接。

第一种方案呢,要先获取服务端证书,然后安装到本地jdk的证书库。我们使用openssl来获取证书信息,这里我写成了一个shell脚本,方便使用。

get_certs_by_domain_port.sh

#!bin/bash
#服务端地址
host=$1
#端口
port=$2

#证书名称
certName=$3

#获取证书
echo "Q"|openssl s_client -connect ${host}:${port} -servername ${host} -showcerts | openssl x509 -outform pem > ${certName}.crt

如果需要循环获取多个证书可以用下面的脚本

#设置域名列表
hosts=(www.baidu.com www.csdn.net www.cnblogs.com)
#设置端口,HTTPS默认端口为443
port=443
#循环获取证书
for host in ${hosts[@]};do
  echo "Q"|openssl s_client -connect ${host}:${port} -servername ${host} -showcerts|openssl x509 -outform pem > ${host}.crt
done

执行sh get_certs_by_domain_port.sh www.baidu.com 443 baidu即可在当前目录下生成名称为baidu.crt的证书。
image.png

使用下面的脚本,将获取到的证书导入到jdk证书库。

import_jdk_certs.sh

#!/bin/bash
#将证书导入到jdk证书库
#证书别名
alias=$1
#证书文件名
fileName=$2

keytool -import -v -trustcacerts -alias ${alias} -file ${fileName} -storepass changeit -keystore ${JAVA_HOME}/jre/lib/security/cacerts

执行sh import_jdk_certs.sh baidu baidu.crt即可将证书导入到jdk证书库(需要使用root用户,否则会没有权限)。
image.png

image.png

使用下面的脚本可以查看已经添加到jdk证书库里的证书信息,如果输出为空则代表没有找到证书。

cat_jdk_certs.sh

#!/bin/bash
certName=$1
keytool -list -keystore "${JAVA_HOME}/jre/lib/security/cacerts" -storepass changeit |grep ${certName}

执行sh cat_jdk_certs.sh baidu 查看。
image.png

第二种方案:取消证书认证,信任所有请求链接。

/**
	 * 获取 HttpClient
	 * 
	 * @param host
	 * @param path
	 * @return
	 * @author 李振华
	 */
	private static CloseableHttpClient wrapClient(String host, String path) {
		CloseableHttpClient httpClient = HttpClientBuilder.create().build();
		if (host != null && host.startsWith("https://")) {
			return sslClient();
		} else if (StringUtil.isBlank(host) && path != null && path.startsWith("https://")) {
			return sslClient();
		}
		return httpClient;
	}

	/**
	 * 在调用SSL之前需要重写验证方法,取消检测SSL 创建ConnectionManager,添加Connection配置信息
	 * 
	 * @return HttpClient 支持https
	 * @author 李振华
	 */
	private static CloseableHttpClient sslClient() {
		try {
			// 在调用SSL之前需要重写验证方法,取消检测SSL
			AppLogger.debug("在调用SSL之前需要重写验证方法,取消检测SSL");
			X509TrustManager trustManager = new X509TrustManager() {

				@Override
				public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
				}

				@Override
				public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
				}

				@Override
				public X509Certificate[] getAcceptedIssuers() {
					return new X509Certificate[0];
				}

			};
			SSLContext ctx = SSLContext.getInstance(SSLConnectionSocketFactory.TLS);
			ctx.init(null, new TrustManager[] { trustManager }, null);
			SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(ctx,
					NoopHostnameVerifier.INSTANCE);
			// 创建Registry
			RequestConfig requestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD_STRICT)
					.setExpectContinueEnabled(Boolean.TRUE)
					.setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST))
					.setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC)).build();
			Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
					.register("http", PlainConnectionSocketFactory.INSTANCE).register("https", socketFactory).build();
			// 创建ConnectionManager,添加Connection配置信息

			PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(
					socketFactoryRegistry);
			CloseableHttpClient closeableHttpClient = HttpClients.custom().setConnectionManager(connectionManager)
					.setDefaultRequestConfig(requestConfig).build();
			return closeableHttpClient;
		} catch (KeyManagementException ex) {
			throw new RuntimeException(ex);
		} catch (NoSuchAlgorithmException ex) {
			throw new RuntimeException(ex);
		}
	}

标题:openssl获取服务端证书并导入到本地jdk证书库+忽略证书检测,解决'unable to find valid certification path to requested target'
作者:从一滴水开始
地址:http://blog.lizhenhua.fun/articles/2020/10/11/1602393321691.html