小言_互联网的博客

https协议证书访问出错3种场景:Git代码、Maven打包、博客爬虫,unable to find valid certification path to requested target

876人阅读  评论(0)

最近3个月,不知道咋回事,突然git访问出现https协议证书错误了。

不巧的是,Maven打包deploy到 https://oss.sonatype.org 也提示类似错误。

 

其实不止以上2种,最近在弄 爬虫时,爬取csdn博客 https 域名,也有类似问题。

已经转载几篇文章了,留作备用:

转载 彻底解决unable to find valid certification path to requested target

https://blog.csdn.net/FansUnion/article/details/102488696

 

转载 解决PKIX:unable to find valid certification path to requested target 的问题

https://blog.csdn.net/FansUnion/article/details/102488655

 

由于连续3次以上,出现这种问题了,因此,很有必要 认真总结下。

 

第1种场景:Git代码报错了。

一直都没问题了,突然出问题了。

 

增加http参数 sslVerify false,不校验https证书。

这是Eclipse其中一种解决方案,下面第3种手动安装证书的方式,没有尝试。

 

 

第2种场景:博客爬虫,CSDN博客https域名报错。

用的WebMagic,最新版本是有个bug的。

核心思想就是:实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法

private SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {

        // 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法

        X509TrustManager trustManager = new X509TrustManager() {

 

            @Override

            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

            }

 

            @Override

            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {

            }

 

            @Override

            public X509Certificate[] getAcceptedIssuers() {

                return null;

            }

 

        };

 

        SSLContext sc = SSLContext.getInstance("SSLv3");

        sc.init(nullnew TrustManager[] { trustManager }, null);

        return sc;

    }

 

 

第3种场景:Maven打包。

自己一直在整理自己的 技术体系和工具类。

jtn-common组件打包时,7月份的时候,已经打包1.0.0到Maven中央仓库了。

今天,突然又报HTTPs协议问题。

这次是最头疼的一次,尝试了3次搞定了。

git拉代码,eclipse支持配置解决。WebMagic报错,可以代码解决。

 

maven这个,只好继续网上找答案,不重复劳动了。

 

先尝试的是:

转载 彻底解决unable to find valid certification path to requested target

https://blog.csdn.net/FansUnion/article/details/102488696

核心思路:手动把目标网站的https证书导出,再用 

keytool -import -alias abc -keystore cacerts -file D://abc.cer

这种命令导入到JDK里。

试了下,没有成功,郁闷了。只好继续找答案。

 

第2种方式,代码导入:

转载 解决PKIX:unable to find valid certification path to requested target 的问题

https://blog.csdn.net/FansUnion/article/details/102488655

第1次,也没成功,没能理解 控制台的提示:

Server sent 1 certificate(s):

1 Subject CN=oss.sonatype.org
Issuer CN=GlobalSign Root CA, C=EN
sha1 22 b5 9a 57 5c dd 2b db ae 71 0f 61 9d ab 65 07 73 69 b6 6e
md5 4a 0e 97 ce 43 11 11 2f 6b 75 45 82 35 1e 34 5f

Enter certificate to add to trusted keystore or 'q' to quit: [1]

输入1,然后Enter,就安装成功了。重启Eclipse,重新Maven打包 deploy,万事大吉。

第1次,我以为又失败了,只好输入 q。

 

 

关键错误信息:unable to find valid certification path to requested target 

 

完整错误,大概如下:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

        at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)

        at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1937)

        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)

        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)

        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1478)

        at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:212)

        at sun.security.ssl.Handshaker.processLoop(Handshaker.java:957)

        at sun.security.ssl.Handshaker.process_record(Handshaker.java:892)

        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1050)

        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363)

        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391)

        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1375)

        at InstallCert.main(InstallCert.java:101)

Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)

        at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)

        at sun.security.validator.Validator.validate(Validator.java:260)

        at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)

        at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)

        at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:105)

        at InstallCert$SavingTrustManager.checkServerTrusted(InstallCert.java:197)

        at sun.security.ssl.AbstractTrustManagerWrapper.checkServerTrusted(SSLContextImpl.java:922)

        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1460)

        ... 8 more

Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

        at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:145)

        at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131)

        at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)

        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)

        ... 16 more

 

 

 

package us.codecraft.webmagic.downloader;

import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.client.CookieStore;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.*;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.protocol.HttpContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import us.codecraft.webmagic.Site;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Map;

/**
 * TODO 默认的SSL有问题,自定义Downloander? 放这里,不好看
 */
public class HttpClientGenerator {

	private transient Logger logger = LoggerFactory.getLogger(getClass());

	private PoolingHttpClientConnectionManager connectionManager;

	public HttpClientGenerator() {
		Registry<ConnectionSocketFactory> reg = RegistryBuilder.<ConnectionSocketFactory> create()
				.register("http", PlainConnectionSocketFactory.INSTANCE)
				.register("https", myBuildSSLConnectionSocketFactory()).build();
		connectionManager = new PoolingHttpClientConnectionManager(reg);
		connectionManager.setDefaultMaxPerRoute(100);
	}

	private SSLConnectionSocketFactory myBuildSSLConnectionSocketFactory() {
		try {
			return new SSLConnectionSocketFactory(createIgnoreVerifySSL(),
					new String[] { "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2" }, null, new DefaultHostnameVerifier());
		} catch (KeyManagementException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Deprecated
	private SSLConnectionSocketFactory buildSSLConnectionSocketFactory() {
		try {
			return new SSLConnectionSocketFactory(createIgnoreVerifySSL()); // 优先绕过安全证书
		} catch (KeyManagementException e) {
			logger.error("ssl connection fail", e);
		} catch (NoSuchAlgorithmException e) {
			logger.error("ssl connection fail", e);
		}
		return SSLConnectionSocketFactory.getSocketFactory();
	}

	private SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
		// 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法
		X509TrustManager trustManager = new X509TrustManager() {

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

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

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

		};

		SSLContext sc = SSLContext.getInstance("SSLv3");
		sc.init(null, new TrustManager[] { trustManager }, null);
		return sc;
	}

	public HttpClientGenerator setPoolSize(int poolSize) {
		connectionManager.setMaxTotal(poolSize);
		return this;
	}

	public CloseableHttpClient getClient(Site site) {
		return generateClient(site);
	}

	private CloseableHttpClient generateClient(Site site) {
		HttpClientBuilder httpClientBuilder = HttpClients.custom();

		httpClientBuilder.setConnectionManager(connectionManager);
		if (site.getUserAgent() != null) {
			httpClientBuilder.setUserAgent(site.getUserAgent());
		} else {
			httpClientBuilder.setUserAgent("");
		}
		if (site.isUseGzip()) {
			httpClientBuilder.addInterceptorFirst(new HttpRequestInterceptor() {

				public void process(final HttpRequest request, final HttpContext context)
						throws HttpException, IOException {
					if (!request.containsHeader("Accept-Encoding")) {
						request.addHeader("Accept-Encoding", "gzip");
					}
				}
			});
		}
		// 解决post/redirect/post 302跳转问题
		httpClientBuilder.setRedirectStrategy(new CustomRedirectStrategy());

		SocketConfig.Builder socketConfigBuilder = SocketConfig.custom();
		socketConfigBuilder.setSoKeepAlive(true).setTcpNoDelay(true);
		socketConfigBuilder.setSoTimeout(site.getTimeOut());
		SocketConfig socketConfig = socketConfigBuilder.build();
		httpClientBuilder.setDefaultSocketConfig(socketConfig);
		connectionManager.setDefaultSocketConfig(socketConfig);
		httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(site.getRetryTimes(), true));
		generateCookie(httpClientBuilder, site);
		return httpClientBuilder.build();
	}

	private void generateCookie(HttpClientBuilder httpClientBuilder, Site site) {
		if (site.isDisableCookieManagement()) {
			httpClientBuilder.disableCookieManagement();
			return;
		}
		CookieStore cookieStore = new BasicCookieStore();
		for (Map.Entry<String, String> cookieEntry : site.getCookies().entrySet()) {
			BasicClientCookie cookie = new BasicClientCookie(cookieEntry.getKey(), cookieEntry.getValue());
			cookie.setDomain(site.getDomain());
			cookieStore.addCookie(cookie);
		}
		for (Map.Entry<String, Map<String, String>> domainEntry : site.getAllCookies().entrySet()) {
			for (Map.Entry<String, String> cookieEntry : domainEntry.getValue().entrySet()) {
				BasicClientCookie cookie = new BasicClientCookie(cookieEntry.getKey(), cookieEntry.getValue());
				cookie.setDomain(domainEntry.getKey());
				cookieStore.addCookie(cookie);
			}
		}
		httpClientBuilder.setDefaultCookieStore(cookieStore);
	}

}

 

 

 

D:\Soft\javaSE1.8\jdk1.8\jre\lib\security>javac InstallCert.java

D:\Soft\javaSE1.8\jdk1.8\jre\lib\security>java InstallCert oss.sonatype.org
Loading KeyStore D:\Soft\javaSE1.8\jdk1.8\jre\lib\security\cacerts...
Opening connection to oss.sonatype.org:443...
Starting SSL handshake...

 

然后一大堆错误提示,输入1,Enter,安装证书就行了。


转载:https://blog.csdn.net/FansUnion/article/details/102489024
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场