开始入手了解下微信公众平台,一入手发现这平台限制真多。申请的接入就搞的蛋疼,必须得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();