2012-08-16 106 views
4

使用案例: 有一個Web服務發佈的https://a.b.c.d/zz?wsdl如何繞過證書在Java Web服務檢查客戶端

我想要做的就是查詢這個URI,如果我得到一個有效的WSDL,我返回布爾值「true」else「false」 現在,如果我通過Chrome瀏覽器訪問此URL,我將不得不手動對cert警告執行接受,然後WSDL被下載。/HttpsURLConnection的

import java.net.URL; 
import java.io.*; 
import javax.net.ssl.HttpsURLConnection; 

public class JavaHttpsExample 
{ 
    public static void main(String[] args) 
    throws Exception 
    { 
    String httpsURL = "https://a.b.c.d/zz/V2.0/api?wsdl"; 
    URL myurl = new URL(httpsURL); 
    HttpsURLConnection con = (HttpsURLConnection)myurl.openConnection(); 
    InputStream ins = con.getInputStream(); 
    InputStreamReader isr = new InputStreamReader(ins); 
    BufferedReader in = new BufferedReader(isr); 

    String inputLine; 

    while ((inputLine = in.readLine()) != null) 
    { 
     System.out.println(inputLine); 
    } 

    in.close(); 
    } 
} 

,我得到一個錯誤:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names matching IP address a.b.c.d found at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source) at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source) at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source) at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source) at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source) at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source) at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Unknown Source) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source) at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source) at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source) at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source) at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source) at JavaHttpsExample.main(JavaHttpsExample.java:14) Caused by: java.security.cert.CertificateException: No subject alternative names matching IP address a.b.c.d found at sun.security.util.HostnameChecker.matchIP(Unknown Source) at sun.security.util.HostnameChecker.match(Unknown Source) at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkIdentity(Unknown Source) at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)

我已經取代了真實IP與ABCD(當然)

回答

14

不要使用掐滅的TrustManager,因爲這使您的應用程序信任everyone。我建議下載該站點提供的證書並將其添加到私人的可信密鑰庫。這可以讓您在沒有對每個人進行綠燈照明的情況下爲該網站設置例外。

我也喜歡這種方法,因爲它不需要更改代碼。

在Chrome中,單擊URL左側的鎖定圖標。然後點擊「證書信息」。轉到「詳細信息」選項卡並單擊「複製到文件」。將其保存爲「base64編碼的X.509(.cer)」到「SITENAME.cer」。

將$ JAVA_HOME/lib/security/cacerts複製到您的應用程序目錄中作爲「mykeystore.jks」。

安裝與證書:

keytool -keystore mykeystore.jks -storepass changeit -importcert -alias SITENAME -trustcacerts -file SITE.cer 

現在,當你運行你的應用程序,告訴它使用專用證書存儲區:

java -Djavax.net.ssl.trustStore=mykeystore.jks ... 
+1

這就是經驗和業餘愛好者之間的區別:)很好的答案 – 2012-08-16 16:28:45

+0

在Chrome 47中,無法保存證書,就我所見。但是,這一步可以通過Firefox完成。 – simon 2016-01-22 09:11:34

+0

@simon它適用於Chrome 47和48上的我。現在,如果您使用的是Mac而不是「複製到文件」,則必須將證書圖標拖到桌面或Finder窗口,然後纔會創建.cer文件。 – 2016-01-22 20:52:51

6

只實現自己信任的經理像下面的代碼

import java.net.URL; 
import java.security.cert.CertificateException; 
import java.security.cert.X509Certificate; 
import java.io.*; 
import javax.net.ssl.HttpsURLConnection; 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.SSLSocketFactory; 
import javax.net.ssl.TrustManager; 
import javax.net.ssl.X509TrustManager; 

public class JavaHttpsExample 
{ 
    public static void main(String[] args) 
    throws Exception 
    { 
    String httpsURL = "https://a.b.c.d/zz?wsdl"; 
    URL myurl = new URL(httpsURL); 
    SSLContext ssl = SSLContext.getInstance("TLSv1"); 
    ssl.init(null, new TrustManager[]{new SimpleX509TrustManager()}, null); 
    SSLSocketFactory factory = ssl.getSocketFactory(); 


    HttpsURLConnection con = (HttpsURLConnection)myurl.openConnection(); 
    con.setSSLSocketFactory(factory); 
    InputStream ins = con.getInputStream(); 
    InputStreamReader isr = new InputStreamReader(ins); 
    BufferedReader in = new BufferedReader(isr); 

    String inputLine; 

    while ((inputLine = in.readLine()) != null) 
    { 
     System.out.println(inputLine); 
    } 

    in.close(); 
    } 
} 

class SimpleX509TrustManager implements X509TrustManager { 
    public void checkClientTrusted(
      X509Certificate[] cert, String s) 
      throws CertificateException { 
    } 

    public void checkServerTrusted(
      X509Certificate[] cert, String s) 
      throws CertificateException { 
     } 

    @Override 
    public X509Certificate[] getAcceptedIssuers() { 
     // TODO Auto-generated method stub 
     return null; 
    } 

} 
+0

在你的源代碼之上,在哪裏呢「SimpleX509TrustManager」來自? – Kolban 2014-12-27 16:27:55