如何使用Apache HttpClient处理无效的SSL证书?

时间:2022-05-30 00:20:44

I know, there are many different questions and so many answers about this problem... But I can't understand...

我知道,关于这个问题有很多不同的问题和答案……但是我不明白……

I have: ubuntu-9.10-desktop-amd64 + NetBeans6.7.1 installed "as is" from off. rep. I need connecting to some site over the HTTPS. For this I use Apache's HttpClient.

我有:ubuntu-9.10 desktop amd64 + NetBeans6.7.1安装"as " from off. rep.我需要通过HTTPS连接到某个网站。为此,我使用Apache的HttpClient。

From tutorial I read:

从教程我读:

"Once you have JSSE correctly installed, secure HTTP communication over SSL should be as
simple as plain HTTP communication." And some example:

“一旦您正确地安装了JSSE, SSL上的安全HTTP通信应该像普通的HTTP通信一样简单。”和一些例子:

HttpClient httpclient = new HttpClient();
GetMethod httpget = new GetMethod("https://www.verisign.com/"); 
try { 
  httpclient.executeMethod(httpget);
  System.out.println(httpget.getStatusLine());
} finally {
  httpget.releaseConnection();
}

By now, I write this:

现在,我写这个:

HttpClient client = new HttpClient();

HttpMethod get = new GetMethod("https://mms.nw.ru");
//get.setDoAuthentication(true);

try {
    int status = client.executeMethod(get);
    System.out.println(status);

    BufferedInputStream is = new BufferedInputStream(get.getResponseBodyAsStream());
    int r=0;byte[] buf = new byte[10];
    while((r = is.read(buf)) > 0) {
        System.out.write(buf,0,r);
    }

} catch(Exception ex) {
    ex.printStackTrace();
}

As a result I have a set of errors:

因此,我有一组错误:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
        at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1627)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:204)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:198)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:994)
        at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:142)
        at sun.security.ssl.Handshaker.processLoop(Handshaker.java:533)
        at sun.security.ssl.Handshaker.process_record(Handshaker.java:471)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:904)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1132)
        at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:643)
        at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:78)
        at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
        at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
        at org.apache.commons.httpclient.HttpConnection.flushRequestOutputStream(HttpConnection.java:828)
        at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:2116)
        at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1096)
        at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398)
        at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
        at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
        at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323)
        at simpleapachehttp.Main.main(Main.java:41)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:302)
        at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:205)
        at sun.security.validator.Validator.validate(Validator.java:235)
        at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:147)
        at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:230)
        at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:270)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:973)
        ... 17 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:191)
        at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:255)
        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:297)
        ... 23 more

What have I to do to create simplest SSL connection? (Probably without KeyManager and Trust manager etc. while.)

我需要做什么来创建最简单的SSL连接?(可能没有KeyManager和Trust manager等)

14 个解决方案

#1


146  

https://mms.nw.ru uses a self-signed certificate which obviously isn't contained in the default set of trust managers.

https://mms.nw.ru使用一个自签名的证书,这显然不包含在默认的信任管理器集合中。

You'll need to one of the following:

你需要做到以下几点:

  • Configure the SSLContext with a TrustManager that accepts any cert (see below)

    使用接受任何证书的信任管理器配置SSLContext(参见下面)

  • Configure the SSLContext with an appropriate trust store that includes your cert

    将SSLContext配置为包含您的证书的适当信任存储。

  • Add the cert for that site to the default java trust store.

    将该站点的cert添加到默认的java信任存储区。

Here is a sample program that creates a (mostly worthless) SSL Context that accepts any cert:

下面是一个示例程序,它创建了一个(几乎毫无价值的)SSL上下文,可以接受任何证书:

import java.net.URL;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class SSLTest {

    public static void main(String [] args) throws Exception {
        // configure the SSLContext with a TrustManager
        SSLContext ctx = SSLContext.getInstance("TLS");
        ctx.init(new KeyManager[0], new TrustManager[] {new DefaultTrustManager()}, new SecureRandom());
        SSLContext.setDefault(ctx);

        URL url = new URL("https://mms.nw.ru");
        HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
        conn.setHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String arg0, SSLSession arg1) {
                return true;
            }
        });
        System.out.println(conn.getResponseCode());
        conn.disconnect();
    }

    private static class DefaultTrustManager implements X509TrustManager {

        @Override
        public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}

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

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

#2


42  

https://mms.nw.ru likely uses a certificate not issued by a certification authority. Consequently, you need to add the certificate to your trusted Java key store as explained in unable to find valid certification path to requested target:

https://mms.nw.ru可能使用的证书不是由认证机构颁发的。因此,您需要将证书添加到受信任的Java密钥存储库中,因为无法找到被请求目标的有效认证路径:

When working on a client that works with an SSL enabled server running in https protocol, you could get error 'unable to find valid certification path to requested target' if the server certificate is not issued by certification authority, but a self signed or issued by a private CMS.

当处理使用在https协议中运行的启用SSL的服务器的客户机时,如果服务器证书不是由认证机构颁发的,而是由私有CMS自签名或颁发的,则可能会出现“无法找到被请求目标的有效认证路径”的错误。

Don't panic. All you need to do is to add the server certificate to your trusted Java key store if your client is written in Java. You might be wondering how as if you can not access the machine where the server is installed. There is a simple program can help you. Please download the Java program and run

不要恐慌。如果您的客户机是用Java编写的,那么您需要做的就是将服务器证书添加到您信任的Java密钥存储库中。您可能想知道,如果无法访问安装服务器的机器,该如何访问呢?有一个简单的程序可以帮助你。请下载Java程序并运行

% java InstallCert _web_site_hostname_

This program opened a connection to the specified host and started an SSL handshake. It printed the exception stack trace of the error that occured and shows you the certificates used by the server. Now it prompts you add the certificate to your trusted KeyStore.

这个程序打开到指定主机的连接并启动SSL握手。它打印发生错误的异常堆栈跟踪,并显示服务器使用的证书。现在,它提示您将证书添加到受信任的密钥存储库中。

If you've changed your mind, enter 'q'. If you really want to add the certificate, enter '1', or other numbers to add other certificates, even a CA certificate, but you usually don't want to do that. Once you have made your choice, the program will display the complete certificate and then added it to a Java KeyStore named 'jssecacerts' in the current directory.

如果你改变主意了,输入q。如果您确实想要添加证书,请输入'1'或其他数字以添加其他证书,甚至是CA证书,但通常您不希望这样做。一旦您做出选择,程序将显示完整的证书,然后将其添加到当前目录中名为“jssecacerts”的Java密钥存储库。

To use it in your program, either configure JSSE to use it as its trust store or copy it into your $JAVA_HOME/jre/lib/security directory. If you want all Java applications to recognize the certificate as trusted and not just JSSE, you could also overwrite the cacerts file in that directory.

要在程序中使用它,可以配置JSSE将它用作信任存储,或者将它复制到您的$JAVA_HOME/jre/lib/security目录中。如果您希望所有Java应用程序识别证书是受信任的,而不仅仅是JSSE,您还可以覆盖该目录中的cacerts文件。

After all that, JSSE will be able to complete a handshake with the host, which you can verify by running the program again.

在完成所有这些之后,JSSE将能够完成与主机的握手,您可以通过再次运行程序来验证这一点。

To get more details, you can check out Leeland's blog No more 'unable to find valid certification path to requested target'

要了解更多细节,你可以查看利兰的博客,不要再“无法找到被请求目标的有效认证路径”

#3


22  

In addition to Pascal Thivent's correct answer, another way is to save the certificate from Firefox (View Certificate -> Details -> export) or openssl s_client and import it into the trust store.

除了Pascal Thivent的正确答案之外,另一种方法是从Firefox(查看证书—>详细信息—>导出)或openssl s_client保存证书并将其导入信任存储库。

You should only do this if you have a way to verify that certificate. Failing that, do it the first time you connect, it will at least give you an error if the certificate changes unexpectedly on subsequent connections.

只有当您有办法验证该证书时,才应该这样做。如果做不到这一点,那么在第一次连接时就这样做,如果证书在后续连接上发生意外的变化,那么至少会给您一个错误。

To import it in a trust store, use:

要在信任存储中导入它,请使用:

keytool -importcert -keystore truststore.jks -file servercert.pem

By default, the default trust store should be lib/security/cacerts and its password should be changeit, see JSSE Reference guide for details.

默认情况下,默认信任存储应该是lib/security/cacerts,其密码应该是changeit,详细信息请参见JSSE参考指南。

If you don't want to allow that certificate globally, but only for these connections, it's possible to create an SSLContext for it:

如果您不希望在全局范围内允许证书,但是只允许这些连接,那么可以为它创建一个SSLContext:

TrustManagerFactory tmf = TrustManagerFactory
    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore ks = KeyStore.getInstance("JKS");
FileInputStream fis = new FileInputStream("/.../truststore.jks");
ks.load(fis, null);
// or ks.load(fis, "thepassword".toCharArray());
fis.close();

tmf.init(ks);

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);

Then, you need to set it up for Apache HTTP Client 3.x by implementing one if its SecureProtocolSocketFactory to use this SSLContext. (There are examples here).

然后,需要为Apache HTTP客户机3设置它。通过实现一个(如果它的SecureProtocolSocketFactory使用此SSLContext)。(例子)。

Apache HTTP Client 4.x (apart from the earliest version) has direct support for passing an SSLContext.

Apache HTTP客户端4。x(除了最早的版本)直接支持传递SSLContext。

#4


10  

From http://hc.apache.org/httpclient-3.x/sslguide.html:

从http://hc.apache.org/httpclient - 3. - x/sslguide.html:

Protocol.registerProtocol("https", 
new Protocol("https", new MySSLSocketFactory(), 443));
HttpClient httpclient = new HttpClient();
GetMethod httpget = new GetMethod("https://www.whatever.com/");
try {
  httpclient.executeMethod(httpget);
      System.out.println(httpget.getStatusLine());
} finally {
      httpget.releaseConnection();
}

Where MySSLSocketFactory example can be found here. It references a TrustManager, which you can modify to trust everything (although you must consider this!)

在这里可以找到MySSLSocketFactory示例。它引用一个TrustManager,您可以修改它以信任一切(尽管您必须考虑这一点!)

#5


8  

The Apache HttpClient 4.5 way:

Apache HttpClient 4.5方式:

org.apache.http.ssl.SSLContextBuilder sslContextBuilder = SSLContextBuilder.create();
sslContextBuilder.loadTrustMaterial(new org.apache.http.conn.ssl.TrustSelfSignedStrategy());
SSLContext sslContext = sslContextBuilder.build();
org.apache.http.conn.ssl.SSLConnectionSocketFactory sslSocketFactory =
        new SSLConnectionSocketFactory(sslContext, new org.apache.http.conn.ssl.DefaultHostnameVerifier());

HttpClientBuilder httpClientBuilder = HttpClients.custom().setSSLSocketFactory(sslSocketFactory);
httpClient = httpClientBuilder.build();

NOTE: org.apache.http.conn.ssl.SSLContextBuilder is deprecated and org.apache.http.ssl.SSLContextBuilder is the new one (notice conn missing from the latter's package name).

注意:org.apache.http.conn.ssl。不赞成使用SSLContextBuilder,并且不赞成使用org.apache.http.ssl。SSLContextBuilder是新的(请注意后面的包名中缺少了conn)。

#6


4  

Once you have a Java Cert Store (by using the great InstallCert class created above), you can get java to use it by passing the "javax.net.ssl.trustStore" param at java startup.

一旦您有了Java Cert存储(通过使用上面创建的伟大的InstallCert类),您就可以通过在Java startup中传递“javax.net.ssl. sa . truststore”param来让Java使用它。

Ex:

例:

java -Djavax.net.ssl.trustStore=/path/to/jssecacerts MyClassName

#7


4  

For Apache HttpClient 4.5+ & Java8:

对于Apache HttpClient 4.5+ & Java8:

SSLContext sslContext = SSLContexts.custom()
        .loadTrustMaterial((chain, authType) -> true).build();

SSLConnectionSocketFactory sslConnectionSocketFactory =
        new SSLConnectionSocketFactory(sslContext, new String[]
        {"SSLv2Hello", "SSLv3", "TLSv1","TLSv1.1", "TLSv1.2" }, null,
        NoopHostnameVerifier.INSTANCE);
CloseableHttpClient client = HttpClients.custom()
        .setSSLSocketFactory(sslConnectionSocketFactory)
        .build();

But if your HttpClient use a ConnectionManager for seeking connection, e.g. like this:

但是如果您的HttpClient使用ConnectionManager来查找连接,例如:

 PoolingHttpClientConnectionManager connectionManager = new 
         PoolingHttpClientConnectionManager();

 CloseableHttpClient client = HttpClients.custom()
            .setConnectionManager(connectionManager)
            .build();

The HttpClients.custom().setSSLSocketFactory(sslConnectionSocketFactory) has no effect, the problem is not resolved.

httpclient .custom(). setsslsocketfactory (sslConnectionSocketFactory)不起作用,问题没有得到解决。

Because that the HttpClient use the specified connectionManager for seeking connection and the specified connectionManager haven't register our customized SSLConnectionSocketFactory. To resolve this, should register the The customized SSLConnectionSocketFactory in the connectionManager. The correct code should like this:

因为HttpClient使用指定的connectionManager来查找连接,而指定的connectionManager没有注册我们定制的SSLConnectionSocketFactory。要解决这个问题,应该在connectionManager中注册定制的SSLConnectionSocketFactory。正确的代码应该是这样的:

PoolingHttpClientConnectionManager connectionManager = new 
    PoolingHttpClientConnectionManager(RegistryBuilder.
                <ConnectionSocketFactory>create()
      .register("http",PlainConnectionSocketFactory.getSocketFactory())
      .register("https", sslConnectionSocketFactory).build());

CloseableHttpClient client = HttpClients.custom()
            .setConnectionManager(connectionManager)
            .build();

#8


3  

Another issue you may run into with self signed test certs is this:

使用自签名测试证书可能遇到的另一个问题是:

java.io.IOException: HTTPS hostname wrong: should be ...

. io .IOException: HTTPS主机名错误:应该是……

This error occurs when you are trying to access a HTTPS url. You might have already installed the server certificate to your JRE's keystore. But this error means that the name of the server certificate does not match with the actual domain name of the server that is mentioned in the URL. This normally happens when you are using a non CA issued certificate.

当您试图访问HTTPS url时发生此错误。您可能已经将服务器证书安装到JRE的密钥存储库中。但是这个错误意味着服务器证书的名称与URL中提到的服务器的实际域名不匹配。这通常发生在您使用非CA颁发的证书时。

This example shows how to write a HttpsURLConnection DefaultHostnameVerifier that ignore the certificates server name:

这个例子展示了如何编写一个HttpsURLConnection DefaultHostnameVerifier,它忽略了证书服务器的名称:

http://www.java-samples.com/showtutorial.php?tutorialid=211

http://www.java-samples.com/showtutorial.php?tutorialid=211

#9


2  

For a way to easily add hosts you trust at runtime without throwing out all checks, try the code here: http://code.google.com/p/self-signed-cert-trust-manager/.

要想在运行时轻松添加信任的主机而不抛出所有检查,请尝试以下代码:http://code.google.com/p/self-signe -cert-trust-manager/。

#10


1  

EasySSLProtocolSocketFactory was giving me problems so I ended up implementing my own ProtocolSocketFactory.

EasySSLProtocolSocketFactory给我带来了一些问题,因此我最终实现了自己的ProtocolSocketFactory。

First you need to register it:

首先你需要注册:

Protocol.registerProtocol("https", new Protocol("https", new TrustAllSSLSocketFactory(), 443));

HttpClient client = new HttpClient();
...

Then implement ProtocolSocketFactory:

然后实现ProtocolSocketFactory:

class TrustAllSSLSocketFactory implements ProtocolSocketFactory {

    public static final TrustManager[] TRUST_ALL_CERTS = new TrustManager[]{
        new X509TrustManager() {
            public void checkClientTrusted(final X509Certificate[] certs, final String authType) {

            }

            public void checkServerTrusted(final X509Certificate[] certs, final String authType) {

            }

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

    private TrustManager[] getTrustManager() {
        return TRUST_ALL_CERTS;
    }

    public Socket createSocket(final String host, final int port, final InetAddress clientHost,
                               final int clientPort) throws IOException {
        return getSocketFactory().createSocket(host, port, clientHost, clientPort);
    }

    @Override
    public Socket createSocket(final String host, final int port, final InetAddress localAddress,
                               final int localPort, final HttpConnectionParams params) throws IOException {
        return createSocket(host, port);
    }

    public Socket createSocket(final String host, final int port) throws IOException {
        return getSocketFactory().createSocket(host, port);
    }

    private SocketFactory getSocketFactory() throws UnknownHostException {
        TrustManager[] trustAllCerts = getTrustManager();

        try {
            SSLContext context = SSLContext.getInstance("SSL");
            context.init(null, trustAllCerts, new SecureRandom());

            final SSLSocketFactory socketFactory = context.getSocketFactory();
            HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory);
            return socketFactory;
        } catch (NoSuchAlgorithmException | KeyManagementException exception) {
            throw new UnknownHostException(exception.getMessage());
        }
    }
}

Note: This is with HttpClient 3.1 and Java 8

注意:这是HttpClient 3.1和Java 8

#11


0  

This link explains the requirement you have step by step. If You are not really concerned which certificate you can proceed with the process in below link.

这个链接解释了你一步一步的要求。如果您不关心可以在下面的链接中继续处理哪个证书。

Note You might want to double check what you are doing since, this is a unsafe operation.

注意,您可能想要再次检查您正在做什么,因为这是一个不安全的操作。

#12


0  

Using the InstallCert to generate the jssecacerts file and do -Djavax.net.ssl.trustStore=/path/to/jssecacerts worked great.

使用InstallCert生成jssecacerts文件并执行-Djavax.net.ssl.trustStore=/path/to/jssecacerts工作得很好。

#13


0  

I'm useing httpclient 3.1.X ,and this works for me

我用httpclient 3.1。X,这对我有用。

        try {
        SSLContext sslContext = SSLContext.getInstance("TLS");
        TrustManager trustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };
        sslContext.init(null, new TrustManager[]{trustManager}, null);
        SslContextSecureProtocolSocketFactory socketFactory = new SslContextSecureProtocolSocketFactory(sslContext,false);
        Protocol.registerProtocol("https", new Protocol("https", (ProtocolSocketFactory) socketFactory, 443));//同样会影响到HttpUtils
    } catch (Throwable e) {
        e.printStackTrace();

}

public class SslContextSecureProtocolSocketFactory implements      SecureProtocolSocketFactory {

private SSLContext sslContext;
private boolean verifyHostname;

public SslContextSecureProtocolSocketFactory(SSLContext sslContext, boolean verifyHostname) {
    this.verifyHostname = true;
    this.sslContext = sslContext;
    this.verifyHostname = verifyHostname;
}

public SslContextSecureProtocolSocketFactory(SSLContext sslContext) {
    this(sslContext, true);
}

public SslContextSecureProtocolSocketFactory(boolean verifyHostname) {
    this((SSLContext)null, verifyHostname);
}

public SslContextSecureProtocolSocketFactory() {
    this((SSLContext)null, true);
}

public synchronized void setHostnameVerification(boolean verifyHostname) {
    this.verifyHostname = verifyHostname;
}

public synchronized boolean getHostnameVerification() {
    return this.verifyHostname;
}

public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) throws IOException, UnknownHostException {
    SSLSocketFactory sf = this.getSslSocketFactory();
    SSLSocket sslSocket = (SSLSocket)sf.createSocket(host, port, clientHost, clientPort);
    this.verifyHostname(sslSocket);
    return sslSocket;
}

public Socket createSocket(String host, int port, InetAddress localAddress, int localPort, HttpConnectionParams params) throws IOException, UnknownHostException, ConnectTimeoutException {
    if(params == null) {
        throw new IllegalArgumentException("Parameters may not be null");
    } else {
        int timeout = params.getConnectionTimeout();
        Socket socket = null;
        SSLSocketFactory socketfactory = this.getSslSocketFactory();
        if(timeout == 0) {
            socket = socketfactory.createSocket(host, port, localAddress, localPort);
        } else {
            socket = socketfactory.createSocket();
            InetSocketAddress localaddr = new InetSocketAddress(localAddress, localPort);
            InetSocketAddress remoteaddr = new InetSocketAddress(host, port);
            socket.bind(localaddr);
            socket.connect(remoteaddr, timeout);
        }

        this.verifyHostname((SSLSocket)socket);
        return socket;
    }
}

public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
    SSLSocketFactory sf = this.getSslSocketFactory();
    SSLSocket sslSocket = (SSLSocket)sf.createSocket(host, port);
    this.verifyHostname(sslSocket);
    return sslSocket;
}

public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
    SSLSocketFactory sf = this.getSslSocketFactory();
    SSLSocket sslSocket = (SSLSocket)sf.createSocket(socket, host, port, autoClose);
    this.verifyHostname(sslSocket);
    return sslSocket;
}

private void verifyHostname(SSLSocket socket) throws SSLPeerUnverifiedException, UnknownHostException {
    synchronized(this) {
        if(!this.verifyHostname) {
            return;
        }
    }

    SSLSession session = socket.getSession();
    String hostname = session.getPeerHost();

    try {
        InetAddress.getByName(hostname);
    } catch (UnknownHostException var10) {
        throw new UnknownHostException("Could not resolve SSL sessions server hostname: " + hostname);
    }

    X509Certificate[] certs = (X509Certificate[])((X509Certificate[])session.getPeerCertificates());
    if(certs != null && certs.length != 0) {
        X500Principal subjectDN = certs[0].getSubjectX500Principal();
        List cns = this.getCNs(subjectDN);
        boolean foundHostName = false;
        Iterator i$ = cns.iterator();
        AntPathMatcher matcher  = new AntPathMatcher();
        while(i$.hasNext()) {
            String cn = (String)i$.next();
            if(matcher.match(cn.toLowerCase(),hostname.toLowerCase())) {
                foundHostName = true;
                break;
            }
        }

        if(!foundHostName) {
            throw new SSLPeerUnverifiedException("HTTPS hostname invalid: expected \'" + hostname + "\', received \'" + cns + "\'");
        }
    } else {
        throw new SSLPeerUnverifiedException("No server certificates found!");
    }
}

private List<String> getCNs(X500Principal subjectDN) {
    ArrayList cns = new ArrayList();
    StringTokenizer st = new StringTokenizer(subjectDN.getName(), ",");

    while(st.hasMoreTokens()) {
        String cnField = st.nextToken();
        if(cnField.startsWith("CN=")) {
            cns.add(cnField.substring(3));
        }
    }

    return cns;
}

protected SSLSocketFactory getSslSocketFactory() {
    SSLSocketFactory sslSocketFactory = null;
    synchronized(this) {
        if(this.sslContext != null) {
            sslSocketFactory = this.sslContext.getSocketFactory();
        }
    }

    if(sslSocketFactory == null) {
        sslSocketFactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
    }

    return sslSocketFactory;
}

public synchronized void setSSLContext(SSLContext sslContext) {
    this.sslContext = sslContext;
}

}

}

#14


0  

For HttpClient, we can do this :

对于HttpClient,我们可以这样做:

SSLContext ctx = SSLContext.getInstance("TLS");
        ctx.init(new KeyManager[0], new TrustManager[] {new DefaultTrustManager()}, new SecureRandom());
        SSLContext.setDefault(ctx);

        String uri = new StringBuilder("url").toString();

        HostnameVerifier hostnameVerifier = new HostnameVerifier() {
            @Override
            public boolean verify(String arg0, SSLSession arg1) {
                return true;
            }
        };

        HttpClient client = HttpClientBuilder.create().setSSLContext(ctx)
                .setSSLHostnameVerifier(hostnameVerifier).build()

#1


146  

https://mms.nw.ru uses a self-signed certificate which obviously isn't contained in the default set of trust managers.

https://mms.nw.ru使用一个自签名的证书,这显然不包含在默认的信任管理器集合中。

You'll need to one of the following:

你需要做到以下几点:

  • Configure the SSLContext with a TrustManager that accepts any cert (see below)

    使用接受任何证书的信任管理器配置SSLContext(参见下面)

  • Configure the SSLContext with an appropriate trust store that includes your cert

    将SSLContext配置为包含您的证书的适当信任存储。

  • Add the cert for that site to the default java trust store.

    将该站点的cert添加到默认的java信任存储区。

Here is a sample program that creates a (mostly worthless) SSL Context that accepts any cert:

下面是一个示例程序,它创建了一个(几乎毫无价值的)SSL上下文,可以接受任何证书:

import java.net.URL;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class SSLTest {

    public static void main(String [] args) throws Exception {
        // configure the SSLContext with a TrustManager
        SSLContext ctx = SSLContext.getInstance("TLS");
        ctx.init(new KeyManager[0], new TrustManager[] {new DefaultTrustManager()}, new SecureRandom());
        SSLContext.setDefault(ctx);

        URL url = new URL("https://mms.nw.ru");
        HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
        conn.setHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String arg0, SSLSession arg1) {
                return true;
            }
        });
        System.out.println(conn.getResponseCode());
        conn.disconnect();
    }

    private static class DefaultTrustManager implements X509TrustManager {

        @Override
        public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}

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

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

#2


42  

https://mms.nw.ru likely uses a certificate not issued by a certification authority. Consequently, you need to add the certificate to your trusted Java key store as explained in unable to find valid certification path to requested target:

https://mms.nw.ru可能使用的证书不是由认证机构颁发的。因此,您需要将证书添加到受信任的Java密钥存储库中,因为无法找到被请求目标的有效认证路径:

When working on a client that works with an SSL enabled server running in https protocol, you could get error 'unable to find valid certification path to requested target' if the server certificate is not issued by certification authority, but a self signed or issued by a private CMS.

当处理使用在https协议中运行的启用SSL的服务器的客户机时,如果服务器证书不是由认证机构颁发的,而是由私有CMS自签名或颁发的,则可能会出现“无法找到被请求目标的有效认证路径”的错误。

Don't panic. All you need to do is to add the server certificate to your trusted Java key store if your client is written in Java. You might be wondering how as if you can not access the machine where the server is installed. There is a simple program can help you. Please download the Java program and run

不要恐慌。如果您的客户机是用Java编写的,那么您需要做的就是将服务器证书添加到您信任的Java密钥存储库中。您可能想知道,如果无法访问安装服务器的机器,该如何访问呢?有一个简单的程序可以帮助你。请下载Java程序并运行

% java InstallCert _web_site_hostname_

This program opened a connection to the specified host and started an SSL handshake. It printed the exception stack trace of the error that occured and shows you the certificates used by the server. Now it prompts you add the certificate to your trusted KeyStore.

这个程序打开到指定主机的连接并启动SSL握手。它打印发生错误的异常堆栈跟踪,并显示服务器使用的证书。现在,它提示您将证书添加到受信任的密钥存储库中。

If you've changed your mind, enter 'q'. If you really want to add the certificate, enter '1', or other numbers to add other certificates, even a CA certificate, but you usually don't want to do that. Once you have made your choice, the program will display the complete certificate and then added it to a Java KeyStore named 'jssecacerts' in the current directory.

如果你改变主意了,输入q。如果您确实想要添加证书,请输入'1'或其他数字以添加其他证书,甚至是CA证书,但通常您不希望这样做。一旦您做出选择,程序将显示完整的证书,然后将其添加到当前目录中名为“jssecacerts”的Java密钥存储库。

To use it in your program, either configure JSSE to use it as its trust store or copy it into your $JAVA_HOME/jre/lib/security directory. If you want all Java applications to recognize the certificate as trusted and not just JSSE, you could also overwrite the cacerts file in that directory.

要在程序中使用它,可以配置JSSE将它用作信任存储,或者将它复制到您的$JAVA_HOME/jre/lib/security目录中。如果您希望所有Java应用程序识别证书是受信任的,而不仅仅是JSSE,您还可以覆盖该目录中的cacerts文件。

After all that, JSSE will be able to complete a handshake with the host, which you can verify by running the program again.

在完成所有这些之后,JSSE将能够完成与主机的握手,您可以通过再次运行程序来验证这一点。

To get more details, you can check out Leeland's blog No more 'unable to find valid certification path to requested target'

要了解更多细节,你可以查看利兰的博客,不要再“无法找到被请求目标的有效认证路径”

#3


22  

In addition to Pascal Thivent's correct answer, another way is to save the certificate from Firefox (View Certificate -> Details -> export) or openssl s_client and import it into the trust store.

除了Pascal Thivent的正确答案之外,另一种方法是从Firefox(查看证书—>详细信息—>导出)或openssl s_client保存证书并将其导入信任存储库。

You should only do this if you have a way to verify that certificate. Failing that, do it the first time you connect, it will at least give you an error if the certificate changes unexpectedly on subsequent connections.

只有当您有办法验证该证书时,才应该这样做。如果做不到这一点,那么在第一次连接时就这样做,如果证书在后续连接上发生意外的变化,那么至少会给您一个错误。

To import it in a trust store, use:

要在信任存储中导入它,请使用:

keytool -importcert -keystore truststore.jks -file servercert.pem

By default, the default trust store should be lib/security/cacerts and its password should be changeit, see JSSE Reference guide for details.

默认情况下,默认信任存储应该是lib/security/cacerts,其密码应该是changeit,详细信息请参见JSSE参考指南。

If you don't want to allow that certificate globally, but only for these connections, it's possible to create an SSLContext for it:

如果您不希望在全局范围内允许证书,但是只允许这些连接,那么可以为它创建一个SSLContext:

TrustManagerFactory tmf = TrustManagerFactory
    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore ks = KeyStore.getInstance("JKS");
FileInputStream fis = new FileInputStream("/.../truststore.jks");
ks.load(fis, null);
// or ks.load(fis, "thepassword".toCharArray());
fis.close();

tmf.init(ks);

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);

Then, you need to set it up for Apache HTTP Client 3.x by implementing one if its SecureProtocolSocketFactory to use this SSLContext. (There are examples here).

然后,需要为Apache HTTP客户机3设置它。通过实现一个(如果它的SecureProtocolSocketFactory使用此SSLContext)。(例子)。

Apache HTTP Client 4.x (apart from the earliest version) has direct support for passing an SSLContext.

Apache HTTP客户端4。x(除了最早的版本)直接支持传递SSLContext。

#4


10  

From http://hc.apache.org/httpclient-3.x/sslguide.html:

从http://hc.apache.org/httpclient - 3. - x/sslguide.html:

Protocol.registerProtocol("https", 
new Protocol("https", new MySSLSocketFactory(), 443));
HttpClient httpclient = new HttpClient();
GetMethod httpget = new GetMethod("https://www.whatever.com/");
try {
  httpclient.executeMethod(httpget);
      System.out.println(httpget.getStatusLine());
} finally {
      httpget.releaseConnection();
}

Where MySSLSocketFactory example can be found here. It references a TrustManager, which you can modify to trust everything (although you must consider this!)

在这里可以找到MySSLSocketFactory示例。它引用一个TrustManager,您可以修改它以信任一切(尽管您必须考虑这一点!)

#5


8  

The Apache HttpClient 4.5 way:

Apache HttpClient 4.5方式:

org.apache.http.ssl.SSLContextBuilder sslContextBuilder = SSLContextBuilder.create();
sslContextBuilder.loadTrustMaterial(new org.apache.http.conn.ssl.TrustSelfSignedStrategy());
SSLContext sslContext = sslContextBuilder.build();
org.apache.http.conn.ssl.SSLConnectionSocketFactory sslSocketFactory =
        new SSLConnectionSocketFactory(sslContext, new org.apache.http.conn.ssl.DefaultHostnameVerifier());

HttpClientBuilder httpClientBuilder = HttpClients.custom().setSSLSocketFactory(sslSocketFactory);
httpClient = httpClientBuilder.build();

NOTE: org.apache.http.conn.ssl.SSLContextBuilder is deprecated and org.apache.http.ssl.SSLContextBuilder is the new one (notice conn missing from the latter's package name).

注意:org.apache.http.conn.ssl。不赞成使用SSLContextBuilder,并且不赞成使用org.apache.http.ssl。SSLContextBuilder是新的(请注意后面的包名中缺少了conn)。

#6


4  

Once you have a Java Cert Store (by using the great InstallCert class created above), you can get java to use it by passing the "javax.net.ssl.trustStore" param at java startup.

一旦您有了Java Cert存储(通过使用上面创建的伟大的InstallCert类),您就可以通过在Java startup中传递“javax.net.ssl. sa . truststore”param来让Java使用它。

Ex:

例:

java -Djavax.net.ssl.trustStore=/path/to/jssecacerts MyClassName

#7


4  

For Apache HttpClient 4.5+ & Java8:

对于Apache HttpClient 4.5+ & Java8:

SSLContext sslContext = SSLContexts.custom()
        .loadTrustMaterial((chain, authType) -> true).build();

SSLConnectionSocketFactory sslConnectionSocketFactory =
        new SSLConnectionSocketFactory(sslContext, new String[]
        {"SSLv2Hello", "SSLv3", "TLSv1","TLSv1.1", "TLSv1.2" }, null,
        NoopHostnameVerifier.INSTANCE);
CloseableHttpClient client = HttpClients.custom()
        .setSSLSocketFactory(sslConnectionSocketFactory)
        .build();

But if your HttpClient use a ConnectionManager for seeking connection, e.g. like this:

但是如果您的HttpClient使用ConnectionManager来查找连接,例如:

 PoolingHttpClientConnectionManager connectionManager = new 
         PoolingHttpClientConnectionManager();

 CloseableHttpClient client = HttpClients.custom()
            .setConnectionManager(connectionManager)
            .build();

The HttpClients.custom().setSSLSocketFactory(sslConnectionSocketFactory) has no effect, the problem is not resolved.

httpclient .custom(). setsslsocketfactory (sslConnectionSocketFactory)不起作用,问题没有得到解决。

Because that the HttpClient use the specified connectionManager for seeking connection and the specified connectionManager haven't register our customized SSLConnectionSocketFactory. To resolve this, should register the The customized SSLConnectionSocketFactory in the connectionManager. The correct code should like this:

因为HttpClient使用指定的connectionManager来查找连接,而指定的connectionManager没有注册我们定制的SSLConnectionSocketFactory。要解决这个问题,应该在connectionManager中注册定制的SSLConnectionSocketFactory。正确的代码应该是这样的:

PoolingHttpClientConnectionManager connectionManager = new 
    PoolingHttpClientConnectionManager(RegistryBuilder.
                <ConnectionSocketFactory>create()
      .register("http",PlainConnectionSocketFactory.getSocketFactory())
      .register("https", sslConnectionSocketFactory).build());

CloseableHttpClient client = HttpClients.custom()
            .setConnectionManager(connectionManager)
            .build();

#8


3  

Another issue you may run into with self signed test certs is this:

使用自签名测试证书可能遇到的另一个问题是:

java.io.IOException: HTTPS hostname wrong: should be ...

. io .IOException: HTTPS主机名错误:应该是……

This error occurs when you are trying to access a HTTPS url. You might have already installed the server certificate to your JRE's keystore. But this error means that the name of the server certificate does not match with the actual domain name of the server that is mentioned in the URL. This normally happens when you are using a non CA issued certificate.

当您试图访问HTTPS url时发生此错误。您可能已经将服务器证书安装到JRE的密钥存储库中。但是这个错误意味着服务器证书的名称与URL中提到的服务器的实际域名不匹配。这通常发生在您使用非CA颁发的证书时。

This example shows how to write a HttpsURLConnection DefaultHostnameVerifier that ignore the certificates server name:

这个例子展示了如何编写一个HttpsURLConnection DefaultHostnameVerifier,它忽略了证书服务器的名称:

http://www.java-samples.com/showtutorial.php?tutorialid=211

http://www.java-samples.com/showtutorial.php?tutorialid=211

#9


2  

For a way to easily add hosts you trust at runtime without throwing out all checks, try the code here: http://code.google.com/p/self-signed-cert-trust-manager/.

要想在运行时轻松添加信任的主机而不抛出所有检查,请尝试以下代码:http://code.google.com/p/self-signe -cert-trust-manager/。

#10


1  

EasySSLProtocolSocketFactory was giving me problems so I ended up implementing my own ProtocolSocketFactory.

EasySSLProtocolSocketFactory给我带来了一些问题,因此我最终实现了自己的ProtocolSocketFactory。

First you need to register it:

首先你需要注册:

Protocol.registerProtocol("https", new Protocol("https", new TrustAllSSLSocketFactory(), 443));

HttpClient client = new HttpClient();
...

Then implement ProtocolSocketFactory:

然后实现ProtocolSocketFactory:

class TrustAllSSLSocketFactory implements ProtocolSocketFactory {

    public static final TrustManager[] TRUST_ALL_CERTS = new TrustManager[]{
        new X509TrustManager() {
            public void checkClientTrusted(final X509Certificate[] certs, final String authType) {

            }

            public void checkServerTrusted(final X509Certificate[] certs, final String authType) {

            }

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

    private TrustManager[] getTrustManager() {
        return TRUST_ALL_CERTS;
    }

    public Socket createSocket(final String host, final int port, final InetAddress clientHost,
                               final int clientPort) throws IOException {
        return getSocketFactory().createSocket(host, port, clientHost, clientPort);
    }

    @Override
    public Socket createSocket(final String host, final int port, final InetAddress localAddress,
                               final int localPort, final HttpConnectionParams params) throws IOException {
        return createSocket(host, port);
    }

    public Socket createSocket(final String host, final int port) throws IOException {
        return getSocketFactory().createSocket(host, port);
    }

    private SocketFactory getSocketFactory() throws UnknownHostException {
        TrustManager[] trustAllCerts = getTrustManager();

        try {
            SSLContext context = SSLContext.getInstance("SSL");
            context.init(null, trustAllCerts, new SecureRandom());

            final SSLSocketFactory socketFactory = context.getSocketFactory();
            HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory);
            return socketFactory;
        } catch (NoSuchAlgorithmException | KeyManagementException exception) {
            throw new UnknownHostException(exception.getMessage());
        }
    }
}

Note: This is with HttpClient 3.1 and Java 8

注意:这是HttpClient 3.1和Java 8

#11


0  

This link explains the requirement you have step by step. If You are not really concerned which certificate you can proceed with the process in below link.

这个链接解释了你一步一步的要求。如果您不关心可以在下面的链接中继续处理哪个证书。

Note You might want to double check what you are doing since, this is a unsafe operation.

注意,您可能想要再次检查您正在做什么,因为这是一个不安全的操作。

#12


0  

Using the InstallCert to generate the jssecacerts file and do -Djavax.net.ssl.trustStore=/path/to/jssecacerts worked great.

使用InstallCert生成jssecacerts文件并执行-Djavax.net.ssl.trustStore=/path/to/jssecacerts工作得很好。

#13


0  

I'm useing httpclient 3.1.X ,and this works for me

我用httpclient 3.1。X,这对我有用。

        try {
        SSLContext sslContext = SSLContext.getInstance("TLS");
        TrustManager trustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };
        sslContext.init(null, new TrustManager[]{trustManager}, null);
        SslContextSecureProtocolSocketFactory socketFactory = new SslContextSecureProtocolSocketFactory(sslContext,false);
        Protocol.registerProtocol("https", new Protocol("https", (ProtocolSocketFactory) socketFactory, 443));//同样会影响到HttpUtils
    } catch (Throwable e) {
        e.printStackTrace();

}

public class SslContextSecureProtocolSocketFactory implements      SecureProtocolSocketFactory {

private SSLContext sslContext;
private boolean verifyHostname;

public SslContextSecureProtocolSocketFactory(SSLContext sslContext, boolean verifyHostname) {
    this.verifyHostname = true;
    this.sslContext = sslContext;
    this.verifyHostname = verifyHostname;
}

public SslContextSecureProtocolSocketFactory(SSLContext sslContext) {
    this(sslContext, true);
}

public SslContextSecureProtocolSocketFactory(boolean verifyHostname) {
    this((SSLContext)null, verifyHostname);
}

public SslContextSecureProtocolSocketFactory() {
    this((SSLContext)null, true);
}

public synchronized void setHostnameVerification(boolean verifyHostname) {
    this.verifyHostname = verifyHostname;
}

public synchronized boolean getHostnameVerification() {
    return this.verifyHostname;
}

public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) throws IOException, UnknownHostException {
    SSLSocketFactory sf = this.getSslSocketFactory();
    SSLSocket sslSocket = (SSLSocket)sf.createSocket(host, port, clientHost, clientPort);
    this.verifyHostname(sslSocket);
    return sslSocket;
}

public Socket createSocket(String host, int port, InetAddress localAddress, int localPort, HttpConnectionParams params) throws IOException, UnknownHostException, ConnectTimeoutException {
    if(params == null) {
        throw new IllegalArgumentException("Parameters may not be null");
    } else {
        int timeout = params.getConnectionTimeout();
        Socket socket = null;
        SSLSocketFactory socketfactory = this.getSslSocketFactory();
        if(timeout == 0) {
            socket = socketfactory.createSocket(host, port, localAddress, localPort);
        } else {
            socket = socketfactory.createSocket();
            InetSocketAddress localaddr = new InetSocketAddress(localAddress, localPort);
            InetSocketAddress remoteaddr = new InetSocketAddress(host, port);
            socket.bind(localaddr);
            socket.connect(remoteaddr, timeout);
        }

        this.verifyHostname((SSLSocket)socket);
        return socket;
    }
}

public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
    SSLSocketFactory sf = this.getSslSocketFactory();
    SSLSocket sslSocket = (SSLSocket)sf.createSocket(host, port);
    this.verifyHostname(sslSocket);
    return sslSocket;
}

public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
    SSLSocketFactory sf = this.getSslSocketFactory();
    SSLSocket sslSocket = (SSLSocket)sf.createSocket(socket, host, port, autoClose);
    this.verifyHostname(sslSocket);
    return sslSocket;
}

private void verifyHostname(SSLSocket socket) throws SSLPeerUnverifiedException, UnknownHostException {
    synchronized(this) {
        if(!this.verifyHostname) {
            return;
        }
    }

    SSLSession session = socket.getSession();
    String hostname = session.getPeerHost();

    try {
        InetAddress.getByName(hostname);
    } catch (UnknownHostException var10) {
        throw new UnknownHostException("Could not resolve SSL sessions server hostname: " + hostname);
    }

    X509Certificate[] certs = (X509Certificate[])((X509Certificate[])session.getPeerCertificates());
    if(certs != null && certs.length != 0) {
        X500Principal subjectDN = certs[0].getSubjectX500Principal();
        List cns = this.getCNs(subjectDN);
        boolean foundHostName = false;
        Iterator i$ = cns.iterator();
        AntPathMatcher matcher  = new AntPathMatcher();
        while(i$.hasNext()) {
            String cn = (String)i$.next();
            if(matcher.match(cn.toLowerCase(),hostname.toLowerCase())) {
                foundHostName = true;
                break;
            }
        }

        if(!foundHostName) {
            throw new SSLPeerUnverifiedException("HTTPS hostname invalid: expected \'" + hostname + "\', received \'" + cns + "\'");
        }
    } else {
        throw new SSLPeerUnverifiedException("No server certificates found!");
    }
}

private List<String> getCNs(X500Principal subjectDN) {
    ArrayList cns = new ArrayList();
    StringTokenizer st = new StringTokenizer(subjectDN.getName(), ",");

    while(st.hasMoreTokens()) {
        String cnField = st.nextToken();
        if(cnField.startsWith("CN=")) {
            cns.add(cnField.substring(3));
        }
    }

    return cns;
}

protected SSLSocketFactory getSslSocketFactory() {
    SSLSocketFactory sslSocketFactory = null;
    synchronized(this) {
        if(this.sslContext != null) {
            sslSocketFactory = this.sslContext.getSocketFactory();
        }
    }

    if(sslSocketFactory == null) {
        sslSocketFactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
    }

    return sslSocketFactory;
}

public synchronized void setSSLContext(SSLContext sslContext) {
    this.sslContext = sslContext;
}

}

}

#14


0  

For HttpClient, we can do this :

对于HttpClient,我们可以这样做:

SSLContext ctx = SSLContext.getInstance("TLS");
        ctx.init(new KeyManager[0], new TrustManager[] {new DefaultTrustManager()}, new SecureRandom());
        SSLContext.setDefault(ctx);

        String uri = new StringBuilder("url").toString();

        HostnameVerifier hostnameVerifier = new HostnameVerifier() {
            @Override
            public boolean verify(String arg0, SSLSession arg1) {
                return true;
            }
        };

        HttpClient client = HttpClientBuilder.create().setSSLContext(ctx)
                .setSSLHostnameVerifier(hostnameVerifier).build()