CAS-Client是SSO系统的客户端工程,在配置HTTPS正常运行后,可能因服务器不信任随意创建的证书或者证书失效等原因导致验证不通过时,会报出异常,具体信息如下:
java.lang.RuntimeException: 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 at org.jasig.cas.client.util.CommonUtils.getResponseFromServer(CommonUtils.java:341) at org.jasig.cas.client.util.CommonUtils.getResponseFromServer(CommonUtils.java:305) at org.jasig.cas.client.validation.AbstractCasProtocolUrlBasedTicketValidator.retrieveResponseFromServer (AbstractCasProtocolUrlBasedTicketValidator.java:50) at org.jasig.cas.client.validation.AbstractUrlBasedTicketValidator.validate(AbstractUrlBasedTicketValidator.java:207) at org.jasig.cas.client.validation.AbstractTicketValidationFilter.doFilter(AbstractTicketValidationFilter.java:169) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.jasig.cas.client.session.SingleSignOutFilter.doFilter(SingleSignOutFilter.java:76) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at cn.jsprun.filter.FileCaptureFilter.doFilter(FileCaptureFilter.java:43) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at cn.jsprun.filter.OnlineFilter.doFilter(OnlineFilter.java:195) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
解决方案:
在CAS-Client工程文件中修改CommonUtils.java类,增加如下代码:
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; } }
然后将上述代码引入之如下位置:
public static String getResponseFromServer(final URL constructedUrl, final HostnameVerifier hostnameVerifier, final String encoding) { URLConnection conn = null; try { trustAllHttpsCertificates(); conn = constructedUrl.openConnection(); if (conn instanceof HttpsURLConnection) { ((HttpsURLConnection)conn).setHostnameVerifier(hostnameVerifier); } final BufferedReader in; if (CommonUtils.isEmpty(encoding)) { in = new BufferedReader(new InputStreamReader(conn.getInputStream())); } else { in = new BufferedReader(new InputStreamReader(conn.getInputStream(), encoding)); } String line; final StringBuilder stringBuffer = new StringBuilder(255); while ((line = in.readLine()) != null) { stringBuffer.append(line); stringBuffer.append("\n"); } return stringBuffer.toString(); } catch (final Exception e) { LOG.error(e.getMessage(), e); throw new RuntimeException(e); } finally { if (conn != null && conn instanceof HttpURLConnection) { ((HttpURLConnection)conn).disconnect(); } } }