栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > .Net

解决 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path buildin

.Net 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

解决 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path buildin

场景:

HttpURLConnection访问https URL,并且下载PDF文件.

异常信息为:

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

原因分析:

google发现stackoverflow上不少人反应,twitter和新浪微博的api也会报这个异常,不少人反映客户端需要导入证书,其实大可不必,如果要导证书的话,用户不得哭了。。

解决方案:

HttpURLConnection访问https并相信所有证书,如下:

import javax.net.ssl.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class PDFTool {
    private static final LoggerControler log = LoggerControler.getLogger(PDFTool.class);

    public static void httpGetByNotSSLAndSaveFile(String httpUrl, String fileName, String savePath) {
        BufferedReader input = null;
        StringBuilder sb = null;
        URL url = null;
        HttpURLConnection con = null;
        try {
            url = new URL(httpUrl);
            try {
                // trust all hosts
                trustAllHosts();
                HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
                if (url.getProtocol().toLowerCase().equals("https")) {
                    https.setHostnameVerifier(DO_NOT_VERIFY);
                    con = https;
                } else {
                    con = (HttpURLConnection) url.openConnection();
                }
                //设置超时间为10秒
                con.setConnectTimeout(10 * 1000);
                //防止屏蔽程序抓取而返回403错误
                con.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36");
                //得到输入流
                InputStream inputStream = con.getInputStream();
                //获取数组
                byte[] getData = readInputStream(inputStream);
                //文件保存位置,如果不存在新建
                File saveDir = new File(savePath);
                if (!saveDir.exists()) {
                    saveDir.mkdir();
                }
                File file = new File(saveDir + File.separator + fileName);
                FileOutputStream fos = new FileOutputStream(file);
                fos.write(getData);
                if (fos != null) {
                    fos.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
                log.info(url + " download success, savePath =" + savePath);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (MalformedURLException e1) {
            e1.printStackTrace();
        } finally {
            // close buffered
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            // disconnecting releases the resources held by a connection so they may be closed or reused
            if (con != null) {
                con.disconnect();
            }
        }
    }

    final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };

    
    private static void trustAllHosts() {
        final String TAG = "trustAllHosts";
        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
            @Override
            public void checkClientTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException {
                log.info(TAG + " checkClientTrusted");
            }

            @Override
            public void checkServerTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException {
                log.info(TAG + " checkServerTrusted");
            }

            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return new java.security.cert.X509Certificate[]{};
            }
        }};
        // Install the all-trusting trust manager
        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    
    public static byte[] readInputStream(InputStream inputStream) throws IOException {
        byte[] buffer = new byte[1024];
        int len = 0;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        while ((len = inputStream.read(buffer)) != -1) {
            bos.write(buffer, 0, len);
        }
        bos.close();
        return bos.toByteArray();
    }
}

测试code:

import org.testng.annotations.Test;

public class PDFToolTest {

    @Test
    public void testSavePDF() {
        String savePath_local = "C:\Users\myName\Desktop\TestPDF";
        String pdfName = "TEST.pdf";
        String pdfURL = "https://www.uhcmedicaresolutions.com/alphadms/ovdms10g/groups/ov/@ov/@highrespdf/documents/highrespdf/4678057.pdf";
        PDFTool.httpGetByNotSSLAndSaveFile(pdfURL, pdfName, savePath_local);
    }
}

可以看出其中与之前的HttpsURLConnection测试代码主要的不同就是加入了

trustAllHosts();
和
https.setHostnameVerifier(DO_NOT_VERIFY);

表示相信所有证书,并且所有host name验证返回true,这样就能定位到之前的异常是证书验证不通过的问题了。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/954155.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号