java后端访问https证书的问题及解决

2022-11-13 18:11:54 解决 证书 后端

java后端通过Https获取图片

    public static void main(String[] args) {
        try {
            BufferedImage image = Imageio.read(new URL("https://10.128.33.56:6202/object/download?pool=s_alarm&id=2dfa47ccaa56ca64c66078588977532e,360,b43e").openStream());
            //输出流
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            ImageIO.write(image, "jpg", stream);
            String str = Base64.encodeBase64String(stream.toByteArray()).replaceAll(" ", "+").replaceAll("\r|\n", "");
            System.out.println(str);
        } catch (Exception e) {
           log.error("获取图片异常",e);
        }
    }

报错如下

因为没有安装证书

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 com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:150)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1476)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:174)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:168)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:846)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.proceSSMessage(ClientHandshaker.java:106)
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:495)
    at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:433)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:815)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.perfORMInitialHandshake(SSLSocketImpl.java:1025)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1038)
    at InstallCert.main(InstallCert.java:63)
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:221)
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:145)
    at sun.security.validator.Validator.validate(Validator.java:203)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:172)
    at InstallCert$SavingTrustManager.checkServerTrusted(InstallCert.java:158)
    at com.sun.net.ssl.internal.ssl.jsseX509TrustManager.checkServerTrusted(SSLContextImpl.java:320)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:839)
    ... 7 more

安装证书,解决

1.浏览器访问此地址,点击证书

2.下载证书

3.将证书复制到jdk目录

D:\program\Java\jdk1.8.0_271\jre\lib\security 下面

  • 安装证书:keytool -import -alias abc -keystore cacerts -file img_https.cer -storepass changeit
  • 删除证书:keytool -delete -keystore cacerts -file img_https.cer -storepass changeit

安装完成。

然后又报错

javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names matching IP address 10.128.33.56 found
    at sun.security.ssl.Alert.createSSLException(Alert.java:131)
    at sun.security.ssl.TransportContext.fatal(TransportContext.java:353)
    at sun.security.ssl.TransportContext.fatal(TransportContext.java:296)
    at sun.security.ssl.TransportContext.fatal(TransportContext.java:291)
    at sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:652)
    at sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:471)
    at sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:367)
    at sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:376)
    at sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:444)
    at sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:422)
    at sun.security.ssl.TransportContext.dispatch(TransportContext.java:183)
    at sun.security.ssl.SSLTransport.decode(SSLTransport.java:154)
    at sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1279)
    at sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1188)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:401)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:373)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:587)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1570)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1498)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:268)
    at java.net.URL.openStream(URL.java:1067)
    at cn.cloudwalk.util.ImageUtils.main(ImageUtils.java:73)
Caused by: java.security.cert.CertificateException: No subject alternative names matching IP address 10.128.33.56 found
    at sun.security.util.HostnameChecker.matchIP(HostnameChecker.java:173)
    at sun.security.util.HostnameChecker.match(HostnameChecker.java:99)
    at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:441)
    at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:422)
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:228)
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:128)
    at sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:636)
    ... 18 common frames omitted

解决

类中加入下面代码,静态块中,程序启动就运行;

测试发现,用下面代码禁用SSL验证,不用导入证书也可正常运行。

 static {
        disableSslVerification();
    }

    private static void disableSslVerification() {
        try
        {
            // Create a trust manager that does not validate certificate chains
            TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
                @Override
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
                @Override
                public void checkClientTrusted(X509Certificate[] certs, String authType) {
                }
                @Override
                public void checkServerTrusted(X509Certificate[] certs, String authType) {
                }
            }
            };

            // Install the all-trusting trust manager
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

            // Create all-trusting host name verifier
            HostnameVerifier allHostsValid = new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            };

            // Install the all-trusting host verifier
            HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
        } catch (NoSuchAlGorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
    }

这样就可以正常访问到https的资源了。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

相关文章