Как обрабатывать недействительные сертификаты SSL с Apache HttpClient?

Я знаю, есть много разных вопросов и так много ответов об этой проблеме... Но я не могу понять...

У меня: ubuntu-9.10-desktop-amd64 + NetBeans6.7.1 установлен "как есть" с выключенного. по донесению Мне нужно подключиться к некоторому сайту через HTTPS. Для этого я использую Apache HttpClient.

Из учебника я прочитал:

"После правильной установки JSSE безопасная HTTP-связь через SSL должна быть
просто как простое 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();
}

К настоящему времени я пишу это:

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();
}

В результате у меня есть множество ошибок:

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

Что я должен сделать, чтобы создать простейшее соединение SSL? (Вероятно, без KeyManager и Trust Manager и т. Д. Пока.)

17 ответов

Решение

https://mms.nw.ru/ использует самозаверяющий сертификат, который явно не содержится в наборе доверенных менеджеров по умолчанию.

Вам понадобится одно из следующих:

  • Сконфигурируйте SSLContext с TrustManager, который принимает любой сертификат (см. Ниже)

  • Настройте SSLContext с соответствующим хранилищем доверия, которое включает в себя ваш сертификат

  • Добавьте сертификат для этого сайта в хранилище доверенных сертификатов Java по умолчанию.

Вот пример программы, которая создает (в основном бесполезный) контекст 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;
        }
    }
}

https://mms.nw.ru/ вероятно, использует сертификат, не выданный центром сертификации. Следовательно, вам нужно добавить сертификат в ваше доверенное хранилище ключей Java, как объяснено при невозможности найти действительный путь сертификации к запрошенной цели:

При работе на клиенте, работающем с сервером с поддержкой SSL, работающим по протоколу https, вы можете получить сообщение об ошибке "невозможно найти действительный путь сертификации к запрошенной цели", если сертификат сервера не выдан центром сертификации, но сам подписан или выдан частная CMS.

Не паникуйте. Все, что вам нужно сделать, это добавить сертификат сервера в ваше хранилище ключей Java, если ваш клиент написан на Java. Вам может быть интересно, как будто вы не можете получить доступ к машине, на которой установлен сервер. Есть простая программа, которая может вам помочь. Пожалуйста, загрузите программу Java и запустите

% java InstallCert _web_site_hostname_

Эта программа открыла соединение с указанным хостом и запустила рукопожатие SSL. Он напечатал трассировку стека исключений ошибки, которая произошла, и показывает вам сертификаты, используемые сервером. Теперь он предлагает вам добавить сертификат в ваш надежный KeyStore.

Если вы передумали, введите "q". Если вы действительно хотите добавить сертификат, введите "1" или другие числа, чтобы добавить другие сертификаты, даже сертификат CA, но вы обычно не хотите этого делать. После того, как вы сделали свой выбор, программа отобразит полный сертификат, а затем добавит его в хранилище ключей Java с именем "jssecacerts" в текущем каталоге.

Чтобы использовать его в своей программе, настройте JSSE на использование его в качестве хранилища доверенных сертификатов или скопируйте его в каталог $JAVA_HOME/jre/lib/security. Если вы хотите, чтобы все приложения Java распознавали сертификат как доверенный, а не только JSSE, вы можете также перезаписать файл cacerts в этом каталоге.

После всего этого JSSE сможет выполнить рукопожатие с хостом, что можно проверить, запустив программу еще раз.

Чтобы получить более подробную информацию, вы можете заглянуть в блог Leeland No more "невозможно найти действительный путь сертификации для запрашиваемой цели".

В дополнение к правильному ответу Pascal Thivent, другим способом является сохранение сертификата из Firefox (Просмотр сертификата -> Подробности -> экспорт) или openssl s_client и импортируйте его в трастовый магазин.

Это следует делать только в том случае, если у вас есть способ проверить этот сертификат. В противном случае, сделайте это при первом подключении, оно по крайней мере выдаст ошибку, если сертификат неожиданно изменится при последующих подключениях.

Чтобы импортировать его в доверенное хранилище, используйте:

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

По умолчанию хранилище доверия по умолчанию должно быть lib/security/cacerts и его пароль должен быть changeit см. Справочное руководство JSSE для деталей.

Если вы не хотите разрешить этот сертификат глобально, но только для этих подключений, можно создать 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);

Затем вам нужно настроить его для Apache HTTP Client 3.x, реализовав его, если его SecureProtocolSocketFactory использовать это SSLContext, (Здесь есть примеры).

Apache HTTP Client 4.x (кроме самой ранней версии) имеет прямую поддержку для передачи SSLContext,

Для 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();

Но если ваш HttpClient использует ConnectionManager для поиска соединения, например, так:

 PoolingHttpClientConnectionManager connectionManager = new 
         PoolingHttpClientConnectionManager();

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

HttpClients.custom().setSSLSocketFactory(sslConnectionSocketFactory)не имеет никакого эффекта, проблема не решена.

Потому что HttpClient использует указанный connectionManager для поиска соединения, а указанный connectionManager не зарегистрировал наш настроенный SSLConnectionSocketFactory. Чтобы решить эту проблему, следует зарегистрировать настроенный SSLConnectionSocketFactory в ConnectionManager. Правильный код должен выглядеть так:

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

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

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();

НОТА: org.apache.http.conn.ssl.SSLContextBuilder устарела и org.apache.http.ssl.SSLContextBuilder новый (уведомление conn отсутствует в названии пакета последнего).

С 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();
}

Где пример MySSLSocketFactory можно найти здесь. Это ссылается на TrustManager, который вы можете изменить, чтобы доверять всему (хотя вы должны учитывать это!)

Хочу вставить ответ здесь:

в Apache HttpClient 4.5.5

Как обработать недействительный сертификат SSL с клиентом Apache 4.5.5?

HttpClient httpClient = HttpClients
            .custom()
            .setSSLContext(new SSLContextBuilder().loadTrustMaterial(null, TrustAllStrategy.INSTANCE).build())
            .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
            .build();

Если у вас есть Java Cert Store (с помощью созданного выше классного класса InstallCert), вы можете заставить его использовать java, передав параметр "javax.net.ssl.trustStore" при запуске java.

Пример:

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

EasySSLProtocolSocketFactory доставлял мне проблемы, поэтому я в итоге реализовал свой собственный ProtocolSocketFactory.

Сначала вам нужно зарегистрировать его:

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

HttpClient client = new HttpClient();
...

Затем реализуйте 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());
        }
    }
}

Примечание: это с HttpClient 3.1 и Java 8

Другая проблема, с которой вы можете столкнуться с самоподписанными тестовыми сертификатами:

java.io.IOException: HTTPS имя хоста неверно: должно быть...

Эта ошибка возникает при попытке доступа к URL-адресу HTTPS. Возможно, вы уже установили сертификат сервера в хранилище ключей вашего JRE. Но эта ошибка означает, что имя сертификата сервера не совпадает с фактическим доменным именем сервера, указанным в URL. Обычно это происходит, когда вы используете сертификат, не выданный центром сертификации.

В этом примере показано, как написать HttpsURLConnection DefaultHostnameVerifier, игнорирующий имя сервера сертификатов:

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

Чтобы легко добавить хосты, которым вы доверяете, во время выполнения, не выбрасывая все проверки, попробуйте код здесь: http://code.google.com/p/self-signed-cert-trust-manager/.

Я столкнулся с той же проблемой, вдруг все мои импортные товары пропали. Я попытался удалить все содержимое моей папки.m2. И пытался все заново импортировать, но все равно ничего не получалось. Наконец, я открыл веб-сайт, на который IDE жаловалась, что не может загрузить его в моем браузере. И увидел сертификат, который он использовал, и увидел в моем

$ keytool -v -list  PATH_TO_JAVA_KEYSTORE

Путь к моему хранилищу ключей был /Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/security/cacerts

этого конкретного сертификата там не было.

Поэтому все, что вам нужно сделать, это снова поместить сертификат в хранилище ключей JAVA JVM. Это можно сделать с помощью приведенной ниже команды.

$ keytool -import -alias ANY_NAME_YOU_WANT_TO_GIVE -file PATH_TO_YOUR_CERTIFICATE -keystore PATH_OF_JAVA_KEYSTORE

Если он запрашивает пароль, попробуйте пароль по умолчанию "changeit". Если вы получили ошибку разрешения при выполнении вышеуказанной команды. В Windows откройте его в режиме администрирования. В Mac и Unix используйте sudo.

После того, как вы успешно добавили ключ, вы можете просмотреть его, используя:

$ keytool -v -list  /Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/security/cacerts 

Вы можете просмотреть только SHA-1, используя команду

$ keytool -list  /Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/security/cacerts 

Использовал следующее вместе с DefaultTrustManager, и он работал в httpclient как charm. Благодаря тонну!! @Kevin и любой другой участник

    SSLContext ctx = null;
    SSLConnectionSocketFactory sslsf = null;
    try {

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

        sslsf = new SSLConnectionSocketFactory(
                ctx,
                new String[] { "TLSv1" },
                null,
                SSLConnectionSocketFactory.getDefaultHostnameVerifier());

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

     CloseableHttpClient client = HttpClients.custom()
            .setSSLSocketFactory(sslsf)
            .build();

С использованием InstallCert генерировать jssecacerts подать и сделать -Djavax.net.ssl.trustStore=/path/to/jssecacerts работал отлично.

Эта ссылка объясняет требование у вас шаг за шагом. Если вас не интересует, какой сертификат вы можете продолжить, перейдите по ссылке ниже.

Примечание. Возможно, вы захотите дважды проверить, что вы делаете, поскольку это небезопасная операция.

Для 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()

Я использую 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;
}

}

Следуйте приведенным ниже инструкциям для Java 1.7, чтобы создать сертификат SSL с помощью файла программы InstallCert.java.

https://github.com/escline/InstallCert

вы должны перезапустить кота

Другие вопросы по тегам