PKIX path validation failed记录java访问https的点点

开始入手了解下微信公众平台,一入手发现这平台限制真多。申请的接入就搞的蛋疼,必须得80端口,但公司一些80端口被占,而且通过3322来转发平台访问不到,想把本地tomcat改为80端口,但linux下改这个端口麻烦,而且涉及到安全性问题,所以办得放弃。无奈自己用ngrok来把本机作了映射,终于这个问题搞定了。

但在获取access_token时又遇到问题,访问的网络是https,这如果用一般的http方式来访问,发生以下错误:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: basic constraints check failed: pathLenConstraint violated - this cert must be the last cert in the certification path1387443143

	at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1611)
	at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:187)
	at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:181)
	at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1035)
	at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:124)
	at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:516)
	at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:454)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:884)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1112)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:623)
	at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:59)
	at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
	at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
	at org.apache.commons.httpclient.HttpConnection.flushRequestOutputStream(HttpConnection.java:827)
	at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:1975)
	at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:993)
	at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:397)
	at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:170)
	at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:396)
	at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:324)
	at com.ever.utils.OAuthUtil.getAccessToken(OAuthUtil.java:48)
	at com.ever.utils.OAuthUtil.main(OAuthUtil.java:129)
Caused by: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: basic constraints check failed: pathLenConstraint violated - this cert must be the last cert in the certification path
	at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:251)
	at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:234)
	at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:158)
	at sun.security.validator.Validator.validate(Validator.java:218)
	at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126)
	at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:209)
	at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:249)
	at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1014)
	... 18 more
Caused by: java.security.cert.CertPathValidatorException: basic constraints check failed: pathLenConstraint violated - this cert must be the last cert in the certification path
	at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:139)
	at sun.security.provider.certpath.PKIXCertPathValidator.doValidate(PKIXCertPathValidator.java:326)
	at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:178)
	at java.security.cert.CertPathValidator.validate(CertPathValidator.java:250)
	at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:246)
	... 25 more
也就是说证书认证失败,查了下网上各种办法不行,而且有些很复杂,比如在tomcat里加证书什么。

现在要解决的就是怎么绕开证书认证,所在在网上找了一往往遍之后,最后发现一个很好的方法,直接忽视所有的证书,反正这个也不会带来什么安全性的问题。

所在又有了以下代码:

static HostnameVerifier hv = new HostnameVerifier() {

		@Override
		public boolean verify(String hostname, SSLSession session) {
			// TODO Auto-generated method stub
			return true;
		}
    };
	
	private static void trustAllHttpsCertificates() {
		try {
			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;
			sc = javax.net.ssl.SSLContext.getInstance("SSL");
			sc.init(null, trustAllCerts, null);
			javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc
					.getSocketFactory());
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (KeyManagementException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	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;
		}
	}
设置一个空的证书,然后再用证书管理器忽视所有证书,最后在获取HttpsURLConnection之前将这些设置进去就OK了。

URL url = new URL(Constants._URL_ACCESS_TOKEN);
			trustAllHttpsCertificates();
			HttpsURLConnection.setDefaultHostnameVerifier(hv);
			HttpsURLConnection httpsConn = (HttpsURLConnection) url.openConnection();

仅以此文记录一些问题。



你可能感兴趣的:(PKIX path validation failed记录java访问https的点点)