2012-08-16 105 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