java httpclinet請求https地址報java.io.IOException: Invalid keystore format 解決辦法
=這又是一次生產問題協查,痛苦的協查。起因是合作方呼叫地址變更,變更後的地址是https協議地址,對方新增了一個.jks的證書庫要載入
程式碼寫完後,一上線發https請求就報錯,因為合作方封裝了一個sdk的包,報錯堆疊資訊沒有向上返回,是返回了一個“加密失敗”,哎。。。。
這裡只能把ssl debug開啟來,開啟方法不太清楚的參考另一篇文章 java ssl除錯開啟ssl debug日誌
開啟後日志看到兩個異常:
java.io.IOException: Invalid keystore format at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:650) at sun.security.provider.JavaKeyStore$JKS.engineLoad(JavaKeyStore.java:55) at java.security.KeyStore.load(KeyStore.java:1445) at cfca.httpclient.connector.HttpClient.initSSL(HttpClient.java:77) at cfca.httpclient.connector.HttpConnector.init(HttpConnector.java:31)
qtp418304857-24, handling exception: 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 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 sun.security.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1937) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296) at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1478) at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:212) at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979) at sun.security.ssl.Handshaker.process_record(Handshaker.java:914) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1050) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1375) at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563) at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185) at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:153) at cfca.httpclient.connector.HttpClient.send(HttpClient.java:152) at cfca.httpclient.connector.HttpConnector.deal(HttpConnector.java:74) at cfca.httpclient.connector.HttpConnector.post(HttpConnector.java:47)
不知道腦子怎麼想的,上來就查第二個異常,花了2天,想了各種辦法,然而沒有解決(路走錯了怎麼能到達終點呢。。。),事實證明,第一個問題解決後,第二個異常也就跟著沒了。查第二個問題看到的一篇文章,雖然沒用到,但是感覺寫的不錯:How to resolve “unable to find valid certification path to requested target” error ? 後面就是加緊解決第一個問題
在網上看到一些處理辦法,說是maven-resources-plugin 在拷貝resources 檔案時進行 encoding 會“誤傷二進位制檔案”導致拷貝到classes下的檔案發生了變化.
我對比了一下,果不其然,對比了下src/main/resources下的jks 檔案和生產執行的classes下的檔案大小不一致,classes目錄下的檔案大了一圈. 嗯,看看別人的處理辦法, filtering=false
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
</resource>
</resources>
趕緊去修改自己的pom.xml,開啟自己的pom要修改的時候看到程式碼:
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources/certificate</directory>
<filtering>false</filtering>
</resource>
</resources>
filtering已經是false了,沒毛病,但是還是不行,這是為啥?(certificate目錄下是.jks檔案),看到個別有的文章說配置了filtering=false 沒效,估計跟我這配置應該是差不多的,參考下面的方法:
後來調整了一下配置:
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>certificate/*.jks</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>certificate/*.jks</include>
</includes>
</resource>
</resources>
再用maven構建,構建後的.jks檔案大小正常,沒有再變大了!專案部署後,請求https地址也能正常返回了。。。
還看到另外一種配置方式:
<build>
...
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<nonFilteredFileExtensions>
<!--這裡是檔案字尾-->
<nonFilteredFileExtension>jks</nonFilteredFileExtension>
</nonFilteredFileExtensions>
</configuration>
</plugin>
</plugins>
</build>
因為上面的配置生效了,下面這個方法就沒有嘗試。有興趣的小夥伴可以自己動動手!希望記下的這次處理過程對大家也有幫助!