java.security.cert.CertificateException:没有主题备用DNS名称匹配

问题描述:

我正在通过REST api编写文件阅读器,简单代码如下:

I am writing a file reader through REST api, simple code as below:

import domain

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.ssl.HttpsURLConnection;
import java.net.MalformedURLException;

public class Verifier{
    public static void main(String args[]) throws IOException
    {
        URL url = new URL("https://somehostname.xx.xxx.net/somecontent?somequery=number");
        try{
            HttpsURLConnection http=(HttpsURLConnection) url.openConnection();
            int reponse = http.getResponseCode();
            //some json processing
            //...
           }catch (MalformedURLException e) {
               e.printStackTrace();
           }catch (IOException e) {
               e.printStackTrace();
           }
    }
}

然后我在第

int reponse = http.getResponseCode();

错误消息是:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative DNS name matching somehostname.xx.xxx.net found.
    at sun.security.ssl.Alerts.getSSLException(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
    at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
    at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
    at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source)
    at sun.security.ssl.ClientHandshaker.processMessage(Unknown Source)
    at sun.security.ssl.Handshaker.processLoop(Unknown Source)
    at sun.security.ssl.Handshaker.process_record(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
    at sun.security.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.getInputStream0(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
    at java.net.HttpURLConnection.getResponseCode(Unknown Source)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(Unknown Source)
    at domain.main(Verifier.java:39)
Caused by: java.security.cert.CertificateException: No subject alternative DNS name matching somehostname.xx.xxx.net found.
    at sun.security.util.HostnameChecker.matchDNS(Unknown Source)
    at sun.security.util.HostnameChecker.match(Unknown Source)
    at sun.security.ssl.X509TrustManagerImpl.checkIdentity(Unknown Source)
    at sun.security.ssl.X509TrustManagerImpl.checkIdentity(Unknown Source)
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(Unknown Source)
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
    ... 15 more

可以通过chrome浏览器检索同一站点中的内容,而无需输入任何用户名或密码(但确实显示了该网站的安全证书在IE资源管理器中而不是在Chrome中存在问题,您可以继续获取json内容,无需输入任何内容).

The content from the same site can be retrieved through the chrome browser, without any username or password (but it did show there is a problem with this website's security certificate in IE explorer, not in Chrome, you can continue to get the json content without typing anything).

我认为JAVA/eclipse中可能存在一些证书问题,也许吗?我该怎么解决?

I am thinking there might be some certificate problem in JAVA/eclipse, maybe? How can I solve it?

谢谢.

SSLContext sc = SSLContext.getInstance( "TLS");
        TrustManager[] tmArr = {new X509TrustManager() {
            @Override
            public void checkClientTrusted(
                    X509Certificate[] paramArrayOfX509Certificate,
                    String paramString) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(
                    X509Certificate[] paramArrayOfX509Certificate,
                    String paramString) throws CertificateException {
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        }};
        sc.init(null, tmArr, new SecureRandom());
        if (isDetail) {
            if (!ValueWidget.isNullOrEmpty(tmArr)) {
                System.out.println("first TrustManager:" + tmArr[0]);
            }
        }
        huc = (HttpsURLConnection) url.openConnection();

            //解决 javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative DNS name matching apis.map.qq.com found.
            ((HttpsURLConnection) huc).setHostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String s, SSLSession sslSession) {
                    return true;
                }
            });