圖片來源:fotolia
延續上一篇"透過wsimport 去產生 web service client 的程式碼" 如果你看到出現這種錯誤訊息:
在stackoverflow 找了許多討論:
[1] stackoverflow - How to use wsimport when server expects client certificate?
[2] stackoverflow - Mutual SSL - getting the key/truststores in the proper formats
[3] stackoverflow - SOAP with mutual SSL - how to send over credentials?
主要分為幾種作法:
範例程式:
另外可以參考的方法 (用來暫時關閉驗證的方法)
匯入的方法有很多種,傳統的方法就是教你利用Keytool去匯入,範例如下:
但是這個方法有一個最大的問題,就是Server.cer和cacerts.jks分別從哪裡來?該怎麼產生?根據sun 官網的描述:
但是如果這個Server 不是你管的該怎麼辦?所以我覺得這個方法也不好用太麻煩,目前看到最好的就是這篇"Resolve : SunCertPathBuilderException: unable to find valid certification path to requested target ",這篇的教學就是教你利用InstallCert.java這隻程式,去匯入Self-sign SSL Certificate。
也就是透過程式去連線HTTPS的網站,然後自動把它的certificate 下載下來,然後再另外儲存成java可以看的懂得cert檔,最後再匯入client 端的 keystore,所以整個步驟就會簡化成:
下載 InstallCert (Code by Andreas Sterbenz, now available on code.google.com)
延伸閱讀: X.509 certificate filename extensions
SunCertPathBuilderException: unable to find valid certification path to requested target那就代表你遇到這個問題了,因為對方的Web Service 連線是使用HTTPS,而且是使用Self-sign SSL Certificate,所以你的jvm不信任它,而且在keystore也沒有找到相對應的key。
在stackoverflow 找了許多討論:
[1] stackoverflow - How to use wsimport when server expects client certificate?
[2] stackoverflow - Mutual SSL - getting the key/truststores in the proper formats
[3] stackoverflow - SOAP with mutual SSL - how to send over credentials?
主要分為幾種作法:
1. 關掉驗證的機制 (不推薦)
範例程式:
Disable Certificate Validation (code from Example Depot):
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null; //這邊就是重點
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (GeneralSecurityException e) {
}
// Now you can access an https URL without having the certificate in the truststore
try {
URL url = new URL("https://hostname/index.html");
} catch (MalformedURLException e) {
}
另外可以參考的方法 (用來暫時關閉驗證的方法)
2. 匯入Self-sign SSL Certificate
匯入的方法有很多種,傳統的方法就是教你利用Keytool去匯入,範例如下:
\bin\keytool -import -v -trustcacerts -alias server-alias -file server.cer -keystore cacerts.jks -keypass changeit -storepass changeit
但是這個方法有一個最大的問題,就是Server.cer和cacerts.jks分別從哪裡來?該怎麼產生?根據sun 官網的描述:
If you are running the client on a different machine, you need to export the tomcat certificate and import into your trustore etc. Use those values while starting your client application.也就是說,你必須先從跑HTTPS的 Server 匯出Key,然後再手動傳到你client所在的機器,步驟如下:
A. 在Server端匯出你的Certificate
On Windows:
%JAVA_HOME%\bin\keytool -export -alias tomcat -file file.cer
On Linux:
$JAVA_HOME/bin/keytool -export -alias tomcat -file file.cer
B. 匯入剛剛匯出的Certificate 到Client 端的 TrustStore:
On Windows:
%JAVA_HOME%\bin\keytool -import -alias serverCert -file RootCert.crt -keystore %JAVA_HOME%\jre\lib\security\cacerts
On Linux:
$JAVA_HOME/bin/keytool -import -alias serverCert -file RootCert.crt -keystore $JAVA_HOME/jre/lib/security/cacerts
C. 匯入後 Client 端必須利用 JAVA_OPTS去指定 TrustStore:
On Windows:
JAVA_OPTS = -Djavax.net.ssl.trustStore="%JAVA_HOME%\jre\lib\security\cacerts" -Djavax.net.ssl.trustStorePassword="changeit"
On Linux:
JAVA_OPTS = -Djavax.net.ssl.trustStore="$JAVA_HOME/jre/lib/security/cacerts" -Djavax.net.ssl.trustStorePassword="changeit"
Ps.
1. 通常cacerts檔案是存在以下路徑: %JAVA_HOME%\jre\lib\security\cacerts
2. Windows 和 Linux trustStore password default 是changeit
但是如果這個Server 不是你管的該怎麼辦?所以我覺得這個方法也不好用太麻煩,目前看到最好的就是這篇"Resolve : SunCertPathBuilderException: unable to find valid certification path to requested target ",這篇的教學就是教你利用InstallCert.java這隻程式,去匯入Self-sign SSL Certificate。
也就是透過程式去連線HTTPS的網站,然後自動把它的certificate 下載下來,然後再另外儲存成java可以看的懂得cert檔,最後再匯入client 端的 keystore,所以整個步驟就會簡化成:
下載 InstallCert (Code by Andreas Sterbenz, now available on code.google.com)
java InstallCert [host]:[port]
keytool -exportcert -keystore jssecacerts -storepass changeit -file output.cert
keytool -importcert -keystore [DESTINATION_KEYSTORE] -file output.cert
延伸閱讀: X.509 certificate filename extensions
Common filename extensions for X.509 certificates are:
- .pem – (Privacy Enhanced Mail) Base64 encoded DER certificate, enclosed between “—–BEGIN CERTIFICATE—–” and “—–END CERTIFICATE—–”
- .cer, .crt, .der – usually in binary DER form, but Base64-encoded certificates are common too (see .pem above)
- .p7b, .p7c – PKCS#7 SignedData structure without data, just certificate(s) or CRL(s)
- .p12 – PKCS#12, may contain certificate(s) (public) and private keys (password protected)
- .pfx – PFX, predecessor of PKCS#12 (usually contains data in PKCS#12 format, e.g, with PFX files generated in IIS)
- PKCS#7 is a standard for signing or encrypting (officially called “enveloping”) data. Since the certificate is needed to verify signed data, it is possible to include them in the SignedData structure. A .P7C file is a degenerated SignedData structure, without any data to sign.
- PKCS#12 evolved from the PFX (Personal inFormation eXchange) standard and is used to exchange public and private objects in a single file.
沒有留言:
張貼留言