2007年4月17日 星期二

unable to find valid certification path to requested target

前些日子由於系統改成使用跨 server 認證方式進行認證,而認證時使用了自己建立的 Certificate 進行 SSL 加密,沒想到原本運作正常的系統就在沒考慮到此部分狀況下出ㄘㄟˊ了!

Caused by: 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 com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:150)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1476)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:174)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:168)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:847)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:106)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:495)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:433)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:815)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1025)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:619)
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.pcc.tools.HttpUtils.getPageContentWithFormAuthentication(HttpUtils.java:147)
at com.pcc.efp.engine.commands.ExecuteRoutingCommand.saveToFile(ExecuteRoutingCommand.java:181)
... 41 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:221)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:145)
at sun.security.validator.Validator.validate(Validator.java:203)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:172)
at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(SSLContextImpl.java:320)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:840)
... 59 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:236)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:194)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:216)
... 64 more


此部分需求為程式存取 web 系統時,進行背景認證後擷取某網址的內容。原本系統是沒有使用 SSL 加密的!因為求好心切(難聽點叫做雞婆),補上自己建立的 SSL Certificate 進行 SSL handshake,以確保機密資料的保密。

發生此問題時,花了不少時間找問題原因,後來有看到一篇文章才點醒 Certificate 是自己作的,Java 怎知去哪裡找 Certificate 呢?在瞭解問題原因後,就動手把自己當初建立的 ca certificate import 到 JDK 內部的 cacerts 中即可讓此問題徹底解決!

keytool -import -file myca.cert -keystore %JAVA_HOME%\jre\lib\security\cacerts -file myca.cert -alias tomcat

PS:還是花點$跟國外 CA 中心買 Certificate 就不會發生這種問題了!不過難唷,公司啥都要摳的。

6 則留言:

匿名 提到...

我重新import之后,还是未能解决问题,请教为何?

Sand 提到...

還是出現"unable to find valid certification path to requested target"嗎?有無其他訊息可參考?

有一點可以先檢查一下,確定 import 的 JDK 與在使用 certification 的 JDK 是同一組嗎?

之前曾碰過機子上裝好幾組 JDK,import 與 tomcat 使用的 JDK 是不同個的。 @@"

程式心得筆記 工程屍的日子 | Mr. 一顆痣 a.k.a. bigd 提到...

Thanks your sharing.

匿名 提到...

Love this blog. I¡¯ll be bookmarking this one. Thanks!

匿名 提到...

怎麼產生
com.sun.net.ssl.internal.ssl.Provider() for pop.mail.yahoo.com.tw

Sand 提到...

ca 憑證不容易取得的,得透過正常管道方可取得,此連結看是否可以協助?