javax.net.ssl.SSLPeerUnverifiedException:主机名与对等方提供的证书主题不匹配

javax.net.ssl.SSLPeerUnverifiedException:主机名与对等方提供的证书主题不匹配,java,ssl,ssl-certificate,apache-httpclient-4.x,wso2-am,Java,Ssl,Ssl Certificate,Apache Httpclient 4.x,Wso2 Am,我关注stackoverflow上的许多链接,并尝试了许多解决方案,但没有一个对我有效。我正在使用WSO2 API管理器version1.9.1。我面临以下错误: Exception in thread "main" javax.net.ssl.SSLPeerUnverifiedException: Host name 'XXXXXXXXX' does not match the certificate subject provided by the peer (CN=localhost, O=

我关注stackoverflow上的许多链接,并尝试了许多解决方案,但没有一个对我有效。我正在使用WSO2 API管理器
version
1.9.1
。我面临以下错误:

Exception in thread "main" javax.net.ssl.SSLPeerUnverifiedException: Host name 'XXXXXXXXX' does not match the certificate subject provided by the peer (CN=localhost, O=WSO2, L=Mountain View, ST=CA, C=US)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.verifyHostname(SSLConnectionSocketFactory.java:465)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:395)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:353)
    at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:134)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353)
    at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
    at com.java.pushNotifications.WSO2DemoClient.main(WSO2DemoClient.java:49)
我开发了以下Java代码。请帮助我这里出了什么问题。我需要以不安全的方式连接,并允许在没有证书的情况下连接到SSL站点

public static void main(String[] args) throws ClientProtocolException, IOException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
        SSLContextBuilder builder = new SSLContextBuilder();
        builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build());

        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", new PlainConnectionSocketFactory())
                .register("https", sslsf)
                .build();

        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
        cm.setMaxTotal(2000);//max connection

    CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf)
                .setConnectionManager(cm).build();

        HttpGet httpGet = new HttpGet("https://XXXXXXXXXX:8243/token");
        CloseableHttpResponse response = httpclient.execute(httpGet);

        String json =" {\"data\":\"grant_type=password&username=test&password=test123\"}";

        try {
            HttpPost httpost = new HttpPost(url);
            httpost.setHeader("Content-Type", "application/x-www-form-urlencoded");
            httpost.setHeader("Authorization", "Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");

            httpost.setEntity(new StringEntity(json));

            HttpResponse httpResponse = httpclient.execute(httpost);

            System.out.println(httpResponse.getStatusLine());
        }
        finally {
            response.close();
        }

        String responseString1 = new BasicResponseHandler().handleResponse(response);
        System.out.println("Response : "+responseString1);
    }
publicstaticvoidmain(String[]args)抛出ClientProtocolException、IOException、nosuchagorithmexception、KeyStoreException、KeyManagementException{
SSLContextBuilder=新的SSLContextBuilder();
loadTrustMaterial(空,新TrustSelfSignedStrategy());
SSLConnectionSocketFactory sslsf=新的SSLConnectionSocketFactory(builder.build());
Registry Registry=RegistryBuilder.create()
.register(“http”,新的PlainConnectionSocketFactory())
.注册(“https”,sslsf)
.build();
PoolightPClientConnectionManager cm=新的PoolightPClientConnectionManager(注册表);
cm.setMaxTotal(2000);//最大连接数
CloseableHttpClient httpclient=HttpClients.custom().setSSLSocketFactory(sslsf)
.setConnectionManager(cm.build();
HttpGet HttpGet=新的HttpGet(“https://XXXXXXXXXX:8243/token");
CloseableHttpResponse response=httpclient.execute(httpGet);
字符串json=“{\'data\”:\“grant\u type=password&username=test&password=test123\”;
试一试{
HttpPost HttpPost=新的HttpPost(url);
setHeader(“内容类型”、“应用程序/x-www-form-urlencoded”);
httpost.setHeader(“授权”、“基本XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX”);
setEntity(新的StringEntity(json));
HttpResponse HttpResponse=httpclient.execute(httpost);
System.out.println(httpResponse.getStatusLine());
}
最后{
response.close();
}
String responseString1=new BasicResponseHandler().HandlerResponse(响应);
System.out.println(“响应:+responseString1”);
}
更换此

CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf)
            .setConnectionManager(cm).build();

如果证书没有签名(甚至没有自签名),那么您可以这样做

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class TrustAllStrategy implements TrustStrategy {
    @Override
    public boolean isTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {
        return true;
    }
}
然后

编辑:这个

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
            sslcontext, //for you this is builder.build()
            SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
);

我花了一个小时试图解决同样的问题。这就是我想到的:

final SSLConnectionSocketFactory sslsf;
try {
    sslsf = new SSLConnectionSocketFactory(SSLContext.getDefault(),
            NoopHostnameVerifier.INSTANCE);
} catch (NoSuchAlgorithmException e) {
    throw new RuntimeException(e);
}

final Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
        .register("http", new PlainConnectionSocketFactory())
        .register("https", sslsf)
        .build();

final PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
cm.setMaxTotal(100);
httpClient = HttpClients.custom()
        .setSSLSocketFactory(sslsf)
        .setConnectionManager(cm)
        .build();
 SSLContextBuilder sslcontext = new SSLContextBuilder();
 sslcontext.loadTrustMaterial(null, new TrustSelfSignedStrategy());
 httpclient = HttpAsyncClients.custom().setSSLContext(sslcontext.build()).setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
      .build();
最终SSL连接插座工厂sslsf;
试一试{
sslsf=新的SSLConnectionSocketFactory(SSLContext.getDefault(),
NoopHostnameVerifier.INSTANCE);
}捕获(无算法异常){
抛出新的运行时异常(e);
}
final Registry Registry=RegistryBuilder.create()
.register(“http”,新的PlainConnectionSocketFactory())
.注册(“https”,sslsf)
.build();
最终PoolightPClientConnectionManager cm=新的PoolightPClientConnectionManager(注册表);
cm.setMaxTotal(100);
httpClient=HttpClients.custom()
.setSSLSocketFactory(sslsf)
.setConnectionManager(cm)
.build();

希望它能够工作,并且不会使用任何不推荐使用的代码(httpclient 4.4.1)。

这就是我想到的:

final SSLConnectionSocketFactory sslsf;
try {
    sslsf = new SSLConnectionSocketFactory(SSLContext.getDefault(),
            NoopHostnameVerifier.INSTANCE);
} catch (NoSuchAlgorithmException e) {
    throw new RuntimeException(e);
}

final Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
        .register("http", new PlainConnectionSocketFactory())
        .register("https", sslsf)
        .build();

final PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
cm.setMaxTotal(100);
httpClient = HttpClients.custom()
        .setSSLSocketFactory(sslsf)
        .setConnectionManager(cm)
        .build();
 SSLContextBuilder sslcontext = new SSLContextBuilder();
 sslcontext.loadTrustMaterial(null, new TrustSelfSignedStrategy());
 httpclient = HttpAsyncClients.custom().setSSLContext(sslcontext.build()).setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
      .build();

感谢所有的解决方案。我已经在网上尝试了1.5天的所有解决方案,现在终于成功了。这是工作代码

 SSLContextBuilder builder = new SSLContextBuilder();
 builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
 SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(builder.build(), NoopHostnameVerifier.INSTANCE);
 Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
            .register("http", new PlainConnectionSocketFactory())
            .register("https", sslConnectionSocketFactory)
            .build();

 PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
 cm.setMaxTotal(100);
 CloseableHttpClient httpclient = HttpClients.custom()
            .setSSLSocketFactory(sslConnectionSocketFactory)
            .setConnectionManager(cm)
            .build();
 HttpPost httpPost = new HttpPost(url);
 httpPost.setEntity(postEntity);
 httpPost.expectContinue();
 CloseableHttpResponse response = httpclient.execute(httpPost);
SSLContextBuilder=新的SSLContextBuilder();
loadTrustMaterial(空,新TrustSelfSignedStrategy());
SSLConnectionSocketFactory SSLConnectionSocketFactory=新的SSLConnectionSocketFactory(builder.build(),NoopHostnameVerifier.INSTANCE);
Registry Registry=RegistryBuilder.create()
.register(“http”,新的PlainConnectionSocketFactory())
.register(“https”,sslConnectionSocketFactory)
.build();
PoolightPClientConnectionManager cm=新的PoolightPClientConnectionManager(注册表);
cm.setMaxTotal(100);
CloseableHttpClient httpclient=HttpClients.custom()
.setSSLSocketFactory(sslConnectionSocketFactory)
.setConnectionManager(cm)
.build();
HttpPost HttpPost=新的HttpPost(url);
httpPost.setEntity(postEntity);
httpPost.expectContinue();
CloseableHttpResponse response=httpclient.execute(httpPost);

在尝试了本页上建议的大多数解决方案和其他相关stackoverflow讨论后,我发现AJC的上述响应适用于apache httpclient 4.5版

原因: 在创建SSLConnectionSocketFactory时,如果在构造函数中未指定HostVerifier,则不会设置它并使用DefaultHostVerifier。所以AJC解决方案的第3行起了作用


(至少这是apache httpclient 4.5.3中的行为)

您需要比较证书中的主机名加上证书中的使用者替代名+您在代码中调用的主机名(在“xxxxxxxxxxxx”上方)。这些似乎不匹配。它背后的概念是http主机名验证,请看,这只起作用,因为您使用的是“-k”选项,它与“-unsecure”相同。那么证书验证没有完成。看看你建议在上面使用哪个版本的HttpClient?啊。在那种情况下,它还不起作用。您还需要将
SSLConnectionSocketFactory.ALLOW\u ALL\u HOSTNAME\u VERIFIER)
提供给您使用
new
创建的SSLConnectionSocketFactory,这是构造函数的参数之一。我对此不清楚?它不允许我在SSLSF中添加SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER这是不推荐使用的,但是可以使用
org.apache.http.conn.ssl.NoopHostnameVerifier
使用NoopHostnameVerifier.INSTANCE而不是不推荐使用的SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)你救了我的一天!不知道为什么这没有多少选票。。。大概30分钟的时间。自从我遇到这个问题以来,我一直在仔细阅读这个话题。谢谢你救了我