如何在Java Web Service客户端中绕过证书检查


问题内容

用例:有一个发布为https:// abcd /
zz?wsdl
的Web服务

我想做的就是查询此URI,如果我收到一个有效的WSDL,则返回一个布尔值“ true”,否则返回“
false”。现在,如果我通过Chrome浏览器访问此URL,则必须手动执行一个接受证书警告上,然后下载WSDL。但是如何通过Java /
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();
  }
}

我得到一个错误:

线程“主”中的异常javax.net.ssl.SSLHandshakeException:java.security.cert.CertificateException:找不到与com.sun.net.ssl.internal.ssl.Alerts.getSSLException的IP地址abcd匹配的使用者替代名称(未知源)的com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(未知源)的com.sun.net.ssl.internal.ssl的Handshaker.fatalSE(未知源)的com.sun.net.ssl的。
com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(未知源)位于com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(未知源)
),位于com.sun.net.ssl.internal.ssl的com.sun.net.ssl.internal.ssl.Handshaker.processLoop(未知源)。
internal.ssl.SSLSocketImpl。com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(未知源)处的com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(未知源)处的readRecord(未知源)。
net.ssl.internal.ssl.SSLSocketImpl.startHandshake(未知来源)在sun.net.www.protocol.https.HttpsClient.afterConnect(未知来源)在sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(未知来源)
)在sun.net.www.protocol.http.HttpURLConnection.getInputStream(未知源)在Java.HttpsExample.main(JavaHttpsExample.java:14)处:java.security.cert.CertificateException:在sun.security.util.HostnameChecker上找不到与IP地址abcd匹配的主题备用名称。位于com.sun.net.ssl.internal.ssl的sun.security.util.HostnameChecker.match(未知源)的matchIP(未知源)。
ssl.X509TrustManagerImpl.checkServerTrusted(未知来源)

我已经用abcd替换了真实IP(当然)


问题答案:

不要使用残缺的TrustManager,因为这会使您的应用程序信任 所有人
。我建议下载该网站提供的证书,并将其添加到一个受信任的私有密钥库中。这样一来,您可以为该站点设置例外,而无需所有人批准。

我也喜欢这种方法,因为它不需要更改代码。

在Chrome浏览器中,点击网址左侧的锁定图标。然后单击“证书信息”。转到“详细信息”选项卡,然后单击“复制到文件”。将其另存为“
SITENAME.cer”作为“ base64编码的X.509(.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 ...