zoukankan      html  css  js  c++  java
  • 解决PKIX path building failed的问题

    Java在请求某些不受信任的https网站时会报:PKIX path building failed

    解决方法一:使用keytool手动导入证书,为JRE环境导入信任证书

    参考:http://www.cnblogs.com/wanghaixing/p/5630070.html

    方法二:使用代码下载证书保存

    参考:https://blog.csdn.net/frankcheng5143/article/details/52164939

    方法三:服务器不信任我们自己创建的证书,所以在代码中忽略证书信任问题。

    参考:http://mengyang.iteye.com/blog/575671

    最后注意:检查eclipse/myeclipse的JDK或JRE,是否为你导入证书的JRE。

    注意:myeclipse是自带JDK的,JDK中自带JRE,而我们通过命令导入的jre是系统环境变量下path的jre。

    两者很可能不是同一个,要改myeclipse的配置。(具体操作很简单,windows-->preferences-->搜索jre)

    方法二代码实现

    功能:把目标host证书保存到jre/lib/security/jssecacerts文件,亲测有效

    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.security.*;
    import javax.net.ssl.*;
    import java.security.cert.*;
    import org.junit.Test;
    
    public class certUtils {
    	private int port = 443;
    	private char[] passphrase="changeit".toCharArray();
    
    	/**
    	 * @param host 例:www.80s.tw
    	 * @param port	https默认为443端口
    	 * @param passphrase keyStore密码
    	 */
    	public void installCert(String host, int port, char[] passphrase) {
    		//文件分隔符
    		char SEP = File.separatorChar;
    		//获取jre/lib/security目录
    		File dir = new File(System.getProperty("java.home") + SEP + "lib" + SEP
    				+ "security");
    		//新建文件jre/lib/security/jssecacerts,向文件输出时文件才真正创建
    		File file = new File(dir, "jssecacerts");
    		//jssecacerts文件不存在时,获取jre/lib/security/cacerts文件索引
    		if (file.isFile() == false) {
    			file = new File(dir, "cacerts");
    		}
    		System.out.println("Loading KeyStore " + file + "...");
    		try {
    			InputStream in = new FileInputStream(file);
    			KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
    			ks.load(in, passphrase);
    			in.close();
    			SSLContext context = SSLContext.getInstance("TLS");
    			TrustManagerFactory tmf = TrustManagerFactory
    					.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    			tmf.init(ks);
    			X509TrustManager defaultTrustManager = (X509TrustManager) tmf
    					.getTrustManagers()[0];
    			SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
    			context.init(null, new TrustManager[] { tm }, null);
    			SSLSocketFactory factory = context.getSocketFactory();
    			
    			//与目标主机进行连接
    			System.out.println("Opening connection to " + host + ":" + port);
    			try {
    				SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
    				socket.setSoTimeout(10000);
    				System.out.println("Starting SSL handshake...");
    				socket.startHandshake();
    				socket.close();
    				System.out.println("No errors, certificate is already trusted");
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    
    			X509Certificate[] chain = tm.chain;
    			if (chain == null) {
    				return;
    			}
    
    			BufferedReader reader = new BufferedReader(new InputStreamReader(
    					System.in));
    			MessageDigest sha1 = MessageDigest.getInstance("SHA1");
    			MessageDigest md5 = MessageDigest.getInstance("MD5");
    			for (int i = 0; i < chain.length; i++) {
    				X509Certificate cert = chain[i];
    				sha1.update(cert.getEncoded());
    				md5.update(cert.getEncoded());
    			}
    			// 默认证书链第一个
    			int index = 0;
    			X509Certificate cert = chain[index];
    			String alias = host + "-" + (index + 1);
    			ks.setCertificateEntry(alias, cert);
    
    			// keyStore保存到文件jssecacerts
    			File jssecacerts = new File(dir, "jssecacerts");
    			OutputStream out = new FileOutputStream(jssecacerts);
    			ks.store(out, passphrase);
    			out.close();
    
    			System.out.println("-----打印cert-----");
    			System.out.println(cert);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    
    	private final char[] HEXDIGITS = "0123456789abcdef".toCharArray();
    
    	private String toHexString(byte[] bytes) {
    		StringBuilder sb = new StringBuilder(bytes.length * 3);
    		for (int b : bytes) {
    			b &= 0xff;
    			sb.append(HEXDIGITS[b >> 4]);
    			sb.append(HEXDIGITS[b & 15]);
    			sb.append(' ');
    		}
    		return sb.toString();
    	}
    
    	private class SavingTrustManager implements X509TrustManager {
    
    		private final X509TrustManager tm;
    		private X509Certificate[] chain;
    
    		SavingTrustManager(X509TrustManager tm) {
    			this.tm = tm;
    		}
    
    		public X509Certificate[] getAcceptedIssuers() {
    			throw new UnsupportedOperationException();
    		}
    
    		public void checkClientTrusted(X509Certificate[] chain, String authType)
    				throws CertificateException {
    			throw new UnsupportedOperationException();
    		}
    
    		public void checkServerTrusted(X509Certificate[] chain, String authType)
    				throws CertificateException {
    			this.chain = chain;
    			tm.checkServerTrusted(chain, authType);
    		}
    	}
    }
    

      

    查看证书

    keytool -list -v -alias aurora -keystore "C:/Program Files/Java/jdk1.7.0_03/jre/lib/security/cacerts" -storepass changeit  
    这条命令是在JDK安装的密钥库中,查找别名是aurora的证书,密钥库口令是changeit。

    删除证书

    keytool -delete -alias aurora -keystore "C:/Program Files/Java/jdk1.7.0_03/jre/lib/security/cacerts" -storepass changeit  
    删除别名是aurora的证书。

    方法三代码实现

      只要在创建connection之前调用两个方法:

      由于有网友这么说:这样做是放弃了证书的认证,那你们用https还有什么意义呢?就好像搭建了一个https的server,最后在认证失败的时候放弃认证,直接选择信任,那么这个https的server就沦落为一个http的server了,而且性能要比http差

      在下就没有测试,请自行测试。

    trustAllHttpsCertificates();
    HttpsURLConnection.setDefaultHostnameVerifier(hv);
    

      

    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;
    		}
    	}
    

      

  • 相关阅读:
    Java SPI机制详解
    ElasticSearch核心概念和原理
    多线程基础-线程创建、线程方法、线程状态等
    MyBatis-日志、分页、一对多or多对一
    MyBatis-注解开发、XML全局配置
    SpringMVC-数据输出、Map、Model、视图解析、处理Json
    SpringMVC-@RequestMapping、@PathVariable、Rest、POJO封装、乱码问题
    lazy loading img 图片延迟加载
    google 地图,多个标记 js库
    Jquery各版本下载,附Jquery官网下载方法
  • 原文地址:https://www.cnblogs.com/zhumengke/p/8846912.html
Copyright © 2011-2022 走看看