最开始网站是 http 的,后来升级成了 https 。内网环境是自己签发的证书,今天准备访问的时候报错了。原来已经加了跳过证书验证的代码了,还是报错了。
原来的设置如下,是在 spring boot 的启动类里设置了一段静态代码,跳过了证书验证:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
@SpringBootApplication
public class MyApplication {
static {
try {
SSLContext sslc;
sslc = SSLContext.getInstance("TLS");
TrustManager[] trustManagerArray = {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 new X509Certificate[0];
}
}};
sslc.init(null, trustManagerArray, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sslc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
});
} catch (Exception e) {
throw new IllegalArgumentException("证书校验异常!");
}
}
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
分析了下,原来应该是针对的:
java.net.HttpURLConnection
而我今天调用的是 apache 的 httpClient ,所以原来的设置就无效了。
就是利用 http client 简单的访问了一个 url ,http client 版本是 : org.apache.httpcomponents:httpclient:jar:4.5.6 。
package com.huitongjy.user.support.util;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
/**
* @author shifengqiang 2022/3/15 6:03 PM
*/
public class TestHttps {
public static void main(String[] args) {
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
try {
String url = "https://xxxxxxx";
HttpGet get = new HttpGet(url);
HttpResponse response = httpClient.execute(get);
String result = EntityUtils.toString(response.getEntity(), "utf-8");
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
结果报错了,异常栈如下:
javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.ssl.Alert.createSSLException(Alert.java:131)
at sun.security.ssl.TransportContext.fatal(TransportContext.java:327)
at sun.security.ssl.TransportContext.fatal(TransportContext.java:270)
at sun.security.ssl.TransportContext.fatal(TransportContext.java:265)
at sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:646)
at sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:465)
at sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:361)
at sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:376)
at sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:451)
at sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:428)
at sun.security.ssl.TransportContext.dispatch(TransportContext.java:184)
at sun.security.ssl.SSLTransport.decode(SSLTransport.java:154)
at sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1198)
at sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1107)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:400)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:372)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:394)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:353)
at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:134)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353)
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
at com.huitongjy.user.support.util.TestHttps.main(TestHttps.java:19)
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:439)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:306)
at sun.security.validator.Validator.validate(Validator.java:271)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:312)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:221)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:128)
at sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:630)
... 24 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:141)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:434)
... 30 more
根据报错信息,查了下是在
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.apache.http.ssl;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import org.apache.http.annotation.Immutable;
@Immutable
public class SSLContexts {
public SSLContexts() {
}
public static SSLContext createDefault() throws SSLInitializationException {
try {
SSLContext sslcontext = SSLContext.getInstance("TLS");
sslcontext.init((KeyManager[])null, (TrustManager[])null, (SecureRandom)null);
return sslcontext;
} catch (NoSuchAlgorithmException var1) {
throw new SSLInitializationException(var1.getMessage(), var1);
} catch (KeyManagementException var2) {
throw new SSLInitializationException(var2.getMessage(), var2);
}
}
public static SSLContext createSystemDefault() throws SSLInitializationException {
try {
return SSLContext.getDefault();
} catch (NoSuchAlgorithmException var1) {
return createDefault();
}
}
public static SSLContextBuilder custom() {
return SSLContextBuilder.create();
}
}
原来 sslContext 自己又重新 new 了,全部初始化为空了。所以之前静态代码设置的 sslContext 自然就不起作用了。
又查了下代码,在:
HttpClientBuilder 里可以设置 sslContext 。
对原来的代码简单的修改了一下就可以了:
package com.huitongjy.user.support.util;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
/**
* @author shifengqiang 2022/3/15 6:03 PM
*/
public class TestHttps {
private static SSLContext ctx;
static {
try {
ctx = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] arg0,
String arg1) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] arg0,
String arg1) throws CertificateException {
}
};
ctx.init(null, new TrustManager[] { tm }, null);
} catch (Exception e) {
System.out.println(e);
}
}
public static void main(String[] args) {
// 在这儿加了 setSSLContext(ctx)
CloseableHttpClient httpClient = HttpClientBuilder.create().setSSLContext(ctx).build();
try {
String url = "https://usersystem-new.testd.huitong.com/ruok";
HttpGet get = new HttpGet(url);
HttpResponse response = httpClient.execute(get);
String result = EntityUtils.toString(response.getEntity(), "utf-8");
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
}
}