java证书--从 Windows 系统导出 PEM 格式的证书

  • 从 Windows 系统导出 PEM 格式的证书
    您可以从 Windows 系统导出 PEM 格式的证书。在 Windows 上,PEM 证书编码称作 Base-64 编码 X.509 (.CER)。 [了解更多内容]https://docs.vmware.com/cn/Horizon-FLEX/1.12/com.vmware.horizon.flex.admin.doc/GUID-A7D8672A-8DDD-4445-AEAC-9DBB4A770944.html
  •  
  •  
  • 关于java访问https资源时,忽略证书信任问题

    white_wwt发布于 2019-03-20

    java程序在访问https资源时,出现报错
    sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    这本质上,是java在访问https资源时的证书信任问题。
    如何解决这个问题呢?
    解决这个问题前,要了解
    1)https通信过程
    客户端在使用HTTPS方式与Web服务器通信时有以下几个步骤,如图所示。
    (1)客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接。
    (2)Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。
    (3)客户端的浏览器与Web服务器开始协商SSL连接的安全等级,也就是信息加密的等级。
    (4)客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。
    (5)Web服务器利用自己的私钥解密出会话密钥。
    (6)Web服务器利用会话密钥加密与客户端之间的通信。

    clipboard.png
    2)java程序的证书信任规则
    如上文所述,客户端会从服务端拿到证书信息。调用端(客户端)会有一个证书信任列表,拿到证书信息后,会判断该证书是否可信任。
    如果是用浏览器访问https资源,发现证书不可信任,一般会弹框告诉用户,对方的证书不可信任,是否继续之类。
    Java虚拟机并不直接使用操作系统的keyring,而是有自己的security manager。与操作系统类似,jdk的security manager默认有一堆的根证书信任。如果你的https站点证书是花钱申请的,被这些根证书所信任,那使用java来访问此https站点会非常方便。因此,如果用java访问https资源,发现证书不可信任,则会报文章开头说到的错误。

    解决问题的方法
    1)将证书导入到jdk的信任证书中(理论上应该可行,未验证)
    2)在客户端(调用端)添加逻辑,忽略证书信任问题
    第一种方法,需要在每台运行该java程序的机器上,都做导入操作,不方便部署,因此,采用第二种方法。下面贴下该方法对应的代码。
    验证可行的代码
    1)先实现验证方法

    HostnameVerifier hv = new HostnameVerifier() {
            public boolean verify(String urlHostName, SSLSession session) {
                System.out.println("Warning: URL Host: " + urlHostName + " vs. "
                                   + session.getPeerHost());
                return true;
            }
        };
     
     private static void trustAllHttpsCertificates() throws Exception {
     javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
     javax.net.ssl.TrustManager tm = new miTM();
     trustAllCerts[0] = tm;
     javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext
     .getInstance("SSL");
     sc.init(null, trustAllCerts, null);
     javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc
     .getSocketFactory());
     }
     
     static class miTM implements javax.net.ssl.TrustManager,
     javax.net.ssl.X509TrustManager {
     public java.security.cert.X509Certificate[] getAcceptedIssuers() {
     return null;
     }
     
     public boolean isServerTrusted(
     java.security.cert.X509Certificate[] certs) {
     return true;
     }
     
     public boolean isClientTrusted(
     java.security.cert.X509Certificate[] certs) {
     return true;
     }
     
     public void checkServerTrusted(
     java.security.cert.X509Certificate[] certs, String authType)
     throws java.security.cert.CertificateException {
     return;
     }
     
     public void checkClientTrusted(
     java.security.cert.X509Certificate[] certs, String authType)
     throws java.security.cert.CertificateException {
     return;
     }
    }
    

    2)在访问https资源前,调用

    trustAllHttpsCertificates();
    HttpsURLConnection.setDefaultHostnameVerifier(hv);

    以下是一个具体的例子:

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    import javax.net.ssl.HostnameVerifier;
    import javax.net.ssl.HttpsURLConnection;
    import javax.net.ssl.SSLSession;
    
    import org.apache.log4j.Logger;
    import org.htmlparser.util.ParserException;
    
    import com.xwtech.parser.GetRequestHtmlParser;
    import com.xwtech.pojo.ExtendCandidate;
    /*
     * GET请求类
     */
    public class GetRequest {
        private String url = "https://b2b.10086.cn/b2b/main/viewNoticeContent.html?noticeBean.id=";
        private Logger logger;
        public GetRequest() {
            logger = Logger.getLogger(GetRequest.class);
        }
        private static void trustAllHttpsCertificates() throws Exception {
            javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
            javax.net.ssl.TrustManager tm = new miTM();
            trustAllCerts[0] = tm;
            javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, null);
            javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        }
        public void getData(String id) {
            this.url = url + id;
            BufferedReader in = null;
            HttpURLConnection conn = null;
            String result = "";
            try {
            //该部分必须在获取connection前调用
                trustAllHttpsCertificates();
                HostnameVerifier hv = new HostnameVerifier() {
                    public boolean verify(String urlHostName, SSLSession session) {
                        logger.info("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost());
                        return true;
                    }
                };
                HttpsURLConnection.setDefaultHostnameVerifier(hv);
                conn = (HttpURLConnection)new URL(url).openConnection();
                // 发送GET请求必须设置如下两行
                conn.setDoInput(true);
                conn.setRequestMethod("GET");
                // flush输出流的缓冲
                in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                String line;
                while ((line = in.readLine()) != null) {
                    result += line;
                }
            } catch (Exception e) {
                logger.error("发送 GET 请求出现异常!\t请求ID:"+id+"\n"+e.getMessage()+"\n");
            } finally {// 使用finally块来关闭输出流、输入流
                try {
                    if (in != null) {
                        in.close();
                    }
                } catch (IOException ex) {
                    logger.error("关闭数据流出错了!\n"+ex.getMessage()+"\n");
                }
            }
            // 获得相应结果result,可以直接处理......
            
        }
        static class miTM implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
    
            public boolean isServerTrusted(java.security.cert.X509Certificate[] certs) {
                return true;
            }
    
            public boolean isClientTrusted(java.security.cert.X509Certificate[] certs) {
                return true;
            }
    
            public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
                    throws java.security.cert.CertificateException {
                return;
            }
    
            public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
                    throws java.security.cert.CertificateException {
                return;
            }
        }
    }

    java

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值