Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/397.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 证书中的主机名没有';不匹配?_Java - Fatal编程技术网

Java 证书中的主机名没有';不匹配?

Java 证书中的主机名没有';不匹配?,java,Java,我尝试使用自签名证书连接到服务器。我使用此代码接受所有证书 public class CertificateAcceptor { public void initializeTrustManager() { try { SSLContext context = SSLContext.getInstance("SSL"); context.init(null, createTrustManager(), new Secure

我尝试使用自签名证书连接到服务器。我使用此代码接受所有证书

public class CertificateAcceptor {

    public void initializeTrustManager() {
        try {
            SSLContext context = SSLContext.getInstance("SSL");
            context.init(null, createTrustManager(), new SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
    }

    private TrustManager[] createTrustManager() {

    TrustManager[] trustAllCerts = new TrustManager[] {
            new X509TrustManager() {

                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                @Override
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    // leave blank to trust all clients
                }

                @Override
                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    // leave blank to trust all servers
                    for (X509Certificate c : chain) {
                        System.out.println(c.toString());
                    }
                }

            }
        };
        return trustAllCerts;
    }

}
然而,我得到了以下错误:

javax.net.ssl.SSLException: hostname in certificate didn't match: <xyz.ch> != <localhost>
    at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:220)
    at org.apache.http.conn.ssl.BrowserCompatHostnameVerifier.verify(BrowserCompatHostnameVerifier.java:54)
    at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:149)
    at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:130)
    at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:339)
    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:123)
    at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:147)
    at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:108)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:415)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576)
javax.net.ssl.SSLException:证书中的主机名不匹配:!=
位于org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:220)
位于org.apache.http.conn.ssl.BrowserCompatHostnameVerifier.verify(BrowserCompatHostnameVerifier.java:54)
位于org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:149)
位于org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:130)
位于org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:339)
位于org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:123)
位于org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:147)
位于org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:108)
位于org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:415)
位于org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641)
位于org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576)

我确信我的证书代码已经执行,那么可能是什么问题呢?

您是否尝试调用
HttpsURLConnection
setDefaultHostnameVerifier

有关示例,请参见此链接:

您可以使用
SSLSocketFactory。允许所有主机名\u验证程序

SSLSocketFactory sf = new SSLSocketFactory(
    SSLContext.getInstance("TLS"),
    SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Scheme sch = new Scheme("https", 443, sf);
httpclient.getConnectionManager().getSchemeRegistry().register(sch);

HttpGet httpget = new HttpGet("https://host/");
...
...

Prashant的答案可能不起作用,因为您还需要初始化
SSLContext

我会这样做

SSLSocketFactory sf=null ;
        SSLContext sslContext = null;
        StringWriter writer;
        try {
            sslContext = SSLContext.getInstance("TLS")  ;
            sslContext.init(null,null,null);
        } catch (NoSuchAlgorithmException e) {
            //<YourErrorHandling>
        }  catch (KeyManagementException e){
            //<YourErrorHandling>
        }

        try{
            sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        } catch(Exception e) {
            //<YourErrorHandling>

    }
        Scheme scheme = new Scheme("https",443,sf);
        httpClient.getConnectionManager().getSchemeRegistry().register(scheme);
SSLSocketFactory sf=null;
SSLContext SSLContext=null;
弦乐作家;
试一试{
sslContext=sslContext.getInstance(“TLS”);
init(null,null,null);
}捕获(无算法异常){
//
}捕获(密钥管理异常e){
//
}
试一试{
sf=新的SSLSocketFactory(sslContext,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
}捕获(例外e){
//
}
方案=新方案(“https”,443,sf);
httpClient.getConnectionManager().getSchemeRegistry().register(方案);

ALLOW\u ALL不是正确答案。您应该使用扩展名为
ext
的keytool以正确的名称设置证书:

keytool -genkeypair \
   -keystore keystore.jks \
  -dname "CN=OLEKSIYS-W3T, OU=Sun Java System Application Server, O=Sun Microsystems, L=Santa Clara, ST=California, C=US" \
  -keypass changeit \
  -storepass changeit \
  -keyalg RSA \
  -keysize 2048 \
  -alias default \
  -ext SAN=DNS:localhost,IP:127.0.0.1 \
  -validity 9999

有关更多详细信息,请参阅。

我的问题是,JavaSE6或更小版本不支持SNI。这意味着,一个IP只能有一个ssl证书。但在我的服务器上,有3个不同的API具有不同的ssl证书。JavaSE7或更高版本支持SNI,一切正常。(或仅在服务器上运行一个api)

问题不在于trustmanager。主机名验证是一个单独的安全步骤,它根据您试图访问的服务器的证书中定义的名称(应该是服务器的域名aka Hostname)检查您请求的URL的域。在您的情况下,您正在使用的URL中的名称与服务器证书中的名称不匹配。这是一个不正确的答案。您应该使用扩展名为“``keytool-genkeypair \-keystore keystore.jks \-dname”的keytool和
ext
来设置具有正确名称的证书,CN=OLEKSIYS-W3T,OU=Sun Java System Application Server,O=Sun Microsystems,L=Santa Clara,ST=California,C=US”\-keypass changeit \-storepass changeit \-keyalg RSA \-keysize 2048 \-alias s1as \-ext SAN=DNS:localhost,IP:127.0.0.1 \-validity 9999```请看这是否确实有效,但@WillSargent是正确的。如果您使用“全部允许”方法,您的应用程序将变得易受攻击。你可能会对一个不太受欢迎的应用程序感到满意,但在工作/自由职业项目上要小心。@Jackson,比这更糟糕。联邦贸易委员会起诉人们以这种方式禁用安全。哦,哇!!我不知道那是真的。令我惊讶的是,联邦贸易委员会一直在努力了解这些事情。谢谢你提供的信息。这个答案在以后的版本中不再适用了。将出现“SSLContextImpl未初始化”异常。使用@Abhishek Tyagi answert而不是在生成密钥库后,您是单独初始化它还是作为
SSLContext
的一部分初始化它?如果您有时间查看我的证书,我将不胜感激。您需要将证书添加到您的信任存储中。通常的方法是使用keytool将其添加到cacerts,或者将系统属性javax.net.ssl.trustStore设置为指向另一个信任存储。