Alert uzgadniania SSL: błąd nierozpoznany_nazwa od aktualizacji do Java 1.7.0

225

Zaktualizowałem dzisiaj z Java 1.6 do Java 1.7. Od tego czasu pojawia się błąd, gdy próbuję nawiązać połączenie z moim serwerem internetowym przez SSL:

javax.net.ssl.SSLProtocolException: handshake alert:  unrecognized_name
    at sun.security.ssl.ClientHandshaker.handshakeAlert(ClientHandshaker.java:1288)
    at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1904)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1027)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1262)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1289)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1273)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:523)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1296)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
    at java.net.URL.openStream(URL.java:1035)

Oto kod:

SAXBuilder builder = new SAXBuilder();
Document document = null;

try {
    url = new URL(https://some url);
    document = (Document) builder.build(url.openStream());
} catch (NoSuchAlgorithmException ex) {
    Logger.getLogger(DownloadLoadiciousComputer.class.getName()).log(Level.SEVERE, null, ex);  
}

To tylko projekt testowy, dlatego pozwalam i używam niezaufanych certyfikatów z kodem:

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

        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        public void checkClientTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
        }

        public void checkServerTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
        }
    }
};

try {

    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new java.security.SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {

    Logger.getLogger(DownloadManager.class.getName()).log(Level.SEVERE, null, e);
} 

Z powodzeniem próbowałem połączyć się z https://google.com . gdzie jest moja wina?

Dzięki.

pvomhoff
źródło

Odpowiedzi:

304

Java 7 wprowadziła obsługę SNI, która jest domyślnie włączona. Dowiedziałem się, że niektóre źle skonfigurowane serwery wysyłają ostrzeżenie „Nierozpoznana nazwa” podczas uzgadniania SSL, które jest ignorowane przez większość klientów… z wyjątkiem Java. Jak wspomniano w @Bob Kerns , inżynierowie Oracle odmawiają „naprawy” tego błędu / funkcji.

Jako obejście sugerują ustawienie jsse.enableSNIExtensionwłaściwości. Aby umożliwić programom pracę bez ponownej kompilacji, uruchom aplikację jako:

java -Djsse.enableSNIExtension=false yourClass

Właściwość można również ustawić w kodzie Java, ale należy ją ustawić przed wszelkimi działaniami SSL . Po załadowaniu biblioteki SSL możesz zmienić właściwość, ale nie będzie to miało żadnego wpływu na status SNI . Aby wyłączyć SNI w czasie wykonywania (z wyżej wymienionymi ograniczeniami), użyj:

System.setProperty("jsse.enableSNIExtension", "false");

Wadą ustawienia tej flagi jest to, że SNI jest wyłączony wszędzie w aplikacji. Aby skorzystać z SNI i nadal obsługiwać źle skonfigurowane serwery:

  1. Utwórz SSLSocketnazwę hosta, z którą chcesz się połączyć. Nazwijmy to sslsock.
  2. Spróbuj uciec sslsock.startHandshake(). Spowoduje to zablokowanie, dopóki nie zostanie wykonane lub zgłoszenie wyjątku w przypadku błędu. Ilekroć wystąpił błąd startHandshake(), otrzymaj komunikat wyjątku. Jeśli jest równy, oznacza to handshake alert: unrecognized_name, że znalazłeś źle skonfigurowany serwer.
  3. Po otrzymaniu unrecognized_nameostrzeżenia (krytycznie w Javie) spróbuj ponownie otworzyć a SSLSocket, ale tym razem bez nazwy hosta. To skutecznie wyłącza SNI (w końcu rozszerzenie SNI polega na dodaniu nazwy hosta do wiadomości ClientHello).

W przypadku serwera proxy Webscarab SSL zatwierdzenie to implementuje konfigurację rezerwową.

Lekensteyn
źródło
5
to działa, dzięki! Klient subversion IntelliJ IDEA miał ten sam błąd podczas łączenia przez HTTPS. Wystarczy zaktualizować plik idea.exe.vmoptions o wiersz: -Djsse.enableSNIExtension = false
Dima,
2
Dla java webstart użyj tego: javaws -J-Djsse.enableSNIExtension = false yourClass
Torsten
Miałem dokładnie ten sam problem z moim klientem Jersey z serwerem odpoczynku https. Okazuje się, że użyłem twojej sztuczki i zadziałała !! dzięki!
shahshi15
4
Dla tych, którzy zastanawiają się nad Javą 8, Oracle nadal nie zmieniło zachowania i nadal wymaga od programisty przechwytywania serwerów, które nie (poprawnie) obsługują SNI: docs.oracle.com/javase/8/docs/technotes/guides/security/jsse /…
Lekensteyn
2
@Blauhirn Skontaktuj się ze wsparciem webhost, powinni naprawić swoją konfigurację. Jeśli używają Apache, spójrz w dół na niektóre zmiany, które należy wprowadzić.
Lekensteyn,
89

Miałem, jak sądzę, ten sam problem. Stwierdziłem, że muszę dostosować konfigurację Apache, aby zawierała nazwę serwera lub nazwę serwera dla hosta.

Ten kod nie powiódł się:

public class a {
   public static void main(String [] a) throws Exception {
      java.net.URLConnection c = new java.net.URL("https://mydomain.com/").openConnection();
      c.setDoOutput(true);
      c.getOutputStream();
   }
}

I ten kod działał:

public class a {
   public static void main(String [] a) throws Exception {
      java.net.URLConnection c = new java.net.URL("https://google.com/").openConnection();
      c.setDoOutput(true);
      c.getOutputStream();
   }
}

Wireshark ujawnił, że podczas TSL / SSL Hello Alert ostrzeżenie (poziom: ostrzeżenie, opis: nierozpoznana nazwa), serwer Hello został wysłany z serwera do klienta. Było to tylko ostrzeżenie, jednak Java 7.1 od razu odpowiedziała „Fatal, Description: U nieoczekiwana wiadomość”, co, jak zakładam, oznacza, że ​​biblioteki Java SSL nie lubią widzieć ostrzeżenia o nierozpoznanej nazwie.

Z Wiki on Transport Layer Security (TLS):

112 Ostrzeżenie o nierozpoznanej nazwie Tylko TLS; Wskaźnik nazwy serwera klienta określa nazwę hosta nieobsługiwaną przez serwer

Doprowadziło mnie to do spojrzenia na moje pliki konfiguracyjne Apache i doszedłem do wniosku, że jeśli dodałem ServerName lub ServerAlias ​​dla nazwy wysłanej ze strony klienta / java, działałoby to poprawnie bez żadnych błędów.

<VirtualHost mydomain.com:443>
  ServerName mydomain.com
  ServerAlias www.mydomain.com
David McLaughlin
źródło
3
Wygląda to na błąd w implementacji TLS Javy.
Paŭlo Ebermann
1
Naprawdę otwieram na to błąd. Przypisałem ten numer (jeszcze niewidoczny): bugs.sun.com/bugdatabase/view_bug.do?bug_id=7127374
eckes
1
Dzięki, dodając ServerAliaspracował dla mnie. Widziałem ten sam alert TLS w Wireshark.
Jared Beck
2
To również działało dla mnie. (działałby lepiej, gdybym w to uwierzył i nie poszedł na inną ścieżkę)
użytkownik końcowy
10
@JosephShraibman, twierdzenie, że pracownik Oracle jest idiotą, jest niewłaściwe. Gdy użyjesz dwóch ServerNames, Apache odpowiada unrecognized_name ostrzeżeniem (które może być również ostrzeżeniem śmiertelnym ). RFC 6066 precyzyjnie mówi to na ten temat: „ NIE ZALECA się wysyłania alertu na poziomie ostrzeżenia nierozpoznany_nazwa (112), ponieważ zachowanie klienta w odpowiedzi na alerty na poziomie ostrzeżenia jest nieprzewidywalne. ”. Jedynym błędem popełnianym przez tego pracownika jest założenie, że był to śmiertelny alarm. Jest to zarówno błąd JRE, jak i Apache.
Bruno
36

Możesz wyłączyć wysyłanie rekordów SNI za pomocą właściwości Systemu jsse.enableSNIExtension = false.

Jeśli możesz zmienić kod, pomaga w użyciu SSLCocketFactory#createSocket()(bez parametru hosta lub z podłączonym gniazdem). W takim przypadku nie wyśle ​​wskazania nazwa_serwera.

eckes
źródło
11
System.setProperty ("jsse.enableSNIExtension", "false");
Wykonuje się
Przekonałem się, że to nie zawsze działa. Nie wiem, dlaczego to działa w niektórych przypadkach, a nie w innych.
Joseph Shraibman,
2
Działa dla mnie z -Djsse.enableSNIExtension=false. Ale co jeszcze to robi? Czy jest to szkodliwe dla reszty bezpieczeństwa Java?
ceving
2
Nie, oznacza to po prostu, że niektóre witryny (zwłaszcza serwery sieciowe), które używają wielu nazw hostów za wspólnym adresem IP, nie wiedzą, jaki certyfikat wysłać. Ale jeśli Twoja aplikacja Java nie będzie musiała łączyć się z milionami witryn internetowych, nie będziesz potrzebować tej funkcji. Jeśli napotkasz taki serwer, weryfikacja certyfikatu może się nie powieść i połączenie zostanie przerwane. Nie oczekuje się więc żadnego problemu z bezpieczeństwem.
eckes
17

Wystąpił również ten błąd w nowej wersji serwera Apache.

W naszym przypadku poprawka polegała na zdefiniowaniu ServerAliasw nazwie httpd.confodpowiadającej nazwie hosta, z którym Java próbowała się połączyć. Nasz ServerNameustawiono na wewnętrzną nazwę hosta. Nasz certyfikat SSL używał zewnętrznej nazwy hosta, ale to nie wystarczyło, aby uniknąć ostrzeżenia.

Aby pomóc w debugowaniu, możesz użyć tego polecenia ssl:

openssl s_client -servername <hostname> -connect <hostname>:443 -state

Jeśli występuje problem z tą nazwą hosta, wydrukuje ten komunikat u góry wyjścia:

SSL3 alert read: warning:unrecognized name

Powinienem również zauważyć, że nie dostaliśmy tego błędu podczas używania tego polecenia do łączenia się z wewnętrzną nazwą hosta, mimo że nie był on zgodny z certyfikatem SSL.

Scott McIntyre
źródło
6
Dziękujemy za podanie przykładu odtworzenia problemu przy użyciu openssl. To bardzo pomocne.
sideshowbarker
2
Czy istnieje sposób, aby klient openssl mógł zobaczyć różnicę nazwy, która pochodzi z wiadomości SSL3 alert read: warning:unrecognized name? Widzę wydrukowany alert, ale wynik nie pomaga mi dostrzec tej różnicy w nazewnictwie
mox601,
To mi nie działa. Testowane z OpenSSL 1.0.1e-fips 11 Feb 2013, OpenSSL 1.0.2k-fips 26 Jan 2017i LibreSSL 2.6.5.
Greg Dubicki
15

Zamiast polegać na domyślnym mechanizmie hosta wirtualnego w Apache, możesz zdefiniować ostatni wirtualny host typu catchall, który używa dowolnej nazwy serwera i wieloznacznika ServerAlias, np.

ServerName catchall.mydomain.com
ServerAlias *.mydomain.com

W ten sposób możesz użyć SNI, a apache nie odeśle ostrzeżenia SSL.

Oczywiście działa to tylko wtedy, gdy możesz łatwo opisać wszystkie swoje domeny za pomocą składni symboli wieloznacznych.

Erik
źródło
O ile rozumiem, apache wysyła to ostrzeżenie tylko w przypadku, gdy klient używa nazwy nieskonfigurowanej jako ServerName lub ServerAlias. Jeśli więc masz certyfikat wieloznaczny, określ wszystkie używane subdomeny lub użyj *.mydomain.comskładni ServerAlias. Pamiętaj , że możesz dodać wiele aliasów, używając ServerAliasnp ServerAlias *.mydomain.com mydomain.com *.myotherdomain.com.
Michael Paesold,
13

To powinno być przydatne. Aby ponowić próbę wystąpienia błędu SNI w Apache HttpClient 4.4 - najprostszy sposób, jaki wymyśliliśmy (patrz HTTPCLIENT-1522 ):

public class SniHttpClientConnectionOperator extends DefaultHttpClientConnectionOperator {

    public SniHttpClientConnectionOperator(Lookup<ConnectionSocketFactory> socketFactoryRegistry) {
        super(socketFactoryRegistry, null, null);
    }

    @Override
    public void connect(
            final ManagedHttpClientConnection conn,
            final HttpHost host,
            final InetSocketAddress localAddress,
            final int connectTimeout,
            final SocketConfig socketConfig,
            final HttpContext context) throws IOException {
        try {
            super.connect(conn, host, localAddress, connectTimeout, socketConfig, context);
        } catch (SSLProtocolException e) {
            Boolean enableSniValue = (Boolean) context.getAttribute(SniSSLSocketFactory.ENABLE_SNI);
            boolean enableSni = enableSniValue == null || enableSniValue;
            if (enableSni && e.getMessage() != null && e.getMessage().equals("handshake alert:  unrecognized_name")) {
                TimesLoggers.httpworker.warn("Server received saw wrong SNI host, retrying without SNI");
                context.setAttribute(SniSSLSocketFactory.ENABLE_SNI, false);
                super.connect(conn, host, localAddress, connectTimeout, socketConfig, context);
            } else {
                throw e;
            }
        }
    }
}

i

public class SniSSLSocketFactory extends SSLConnectionSocketFactory {

    public static final String ENABLE_SNI = "__enable_sni__";

    /*
     * Implement any constructor you need for your particular application -
     * SSLConnectionSocketFactory has many variants
     */
    public SniSSLSocketFactory(final SSLContext sslContext, final HostnameVerifier verifier) {
        super(sslContext, verifier);
    }

    @Override
    public Socket createLayeredSocket(
            final Socket socket,
            final String target,
            final int port,
            final HttpContext context) throws IOException {
        Boolean enableSniValue = (Boolean) context.getAttribute(ENABLE_SNI);
        boolean enableSni = enableSniValue == null || enableSniValue;
        return super.createLayeredSocket(socket, enableSni ? target : "", port, context);
    }
}

i

cm = new PoolingHttpClientConnectionManager(new SniHttpClientConnectionOperator(socketFactoryRegistry), null, -1, TimeUnit.MILLISECONDS);
Shcheklein
źródło
Jeśli zrobisz to w ten sposób. Jak radzić sobie ze verifyHostname(sslsock, target)w SSLConnectionSocketFactory.createLayeredSocket? Ponieważ targetzmieniono na pusty ciąg, verifyHostnamenie odniesie sukcesu. Czy brakuje mi czegoś oczywistego?
Haozhun,
2
Właśnie tego szukałem, dziękuję bardzo! Nie znalazłem innego sposobu na obsługę SNI i serwerów, które odpowiadają tym ostrzeżeniem „unrecognized_name” w tym samym czasie.
korpe
To rozwiązanie działa, chyba że używasz serwera proxy.
mrog
Po przeprowadzeniu szybkiego debugowania przez kod klienta Apache, zaczynając od VerifyHostname (), nie widzę, jak to może działać przy użyciu DefaultHostnameVerifier. Podejrzewam, że to rozwiązanie wymaga wyłączenia weryfikacji nazwy hosta (np. Za pomocą NoopHostnameVerifier), co NIE jest dobrym pomysłem, ponieważ pozwala na ataki typu man-in-the-middle.
FlyingSheep
11

Posługiwać się:

  • System.setProperty („jsse.enableSNIExtension”, „false”);
  • Uruchom ponownie Tomcat (ważne)
Tomasz Janisiewicz
źródło
6

Wpadłem na ten problem z wiosennym bootowaniem i Jvm 1.7 i 1.8. W AWS nie mieliśmy opcji zmiany ServerName i ServerAlias, aby pasowały (są różne), więc wykonaliśmy następujące czynności:

W build.gradle dodaliśmy:

System.setProperty("jsse.enableSNIExtension", "false")
bootRun.systemProperties = System.properties

To pozwoliło nam ominąć problem z „Nierozpoznaną nazwą”.

Ray Hunter
źródło
5

Niestety nie można podać właściwości systemu do narzędzia jarsigner.exe.

Przesłałem wadę 7177232 , odnosząc się do wady @eckes 7127374 i wyjaśniając, dlaczego została ona błędnie zamknięta.

Moja wada dotyczy w szczególności wpływu na narzędzie jarsigner, ale być może doprowadzi ich to do ponownego otwarcia drugiej wady i właściwego rozwiązania problemu.

AKTUALIZACJA: W rzeczywistości okazuje się, że MOŻESZ dostarczyć właściwości systemowe do narzędzia Jarsigner, po prostu nie ma go w komunikacie pomocy. Posługiwać sięjarsigner -J-Djsse.enableSNIExtension=false

Bob Kerns
źródło
1
Dzięki Bob za kontynuację. Niestety Oracle nadal nie rozumie całej sprawy. Alarm SNI nie jest śmiertelny, może być traktowany śmiertelnie. Ale większość typowych klientów SSL (tj. Przeglądarek) zdecydowała się je zignorować, ponieważ nie jest to prawdziwy problem z bezpieczeństwem (ponieważ nadal musisz sprawdzić certyfikat serwera i wykryłby nieprawidłowe punkty końcowe). Oczywiście to smutne, że urząd certyfikacji nie może ustawić poprawnie skonfigurowanego serwera https.
eckes
2
W rzeczywistości okazuje się, że MOŻESZ dostarczyć właściwości systemowe do narzędzia Jarsigner, po prostu nie ma go w komunikacie pomocy. Jest to opisane w dokumentacji. Głupie mnie za wiarę w tekst online. Oczywiście wykorzystali to jako pretekst do nie naprawienia tego.
Bob Kerns
BTW: Obecnie omawiam ten problem na security-dev @ openjdk iw chwili, gdy go oceniałem, wygląda na to, że Symantec naprawił serwer znaczników czasu GEOTrust, teraz poprawnie akceptuje adres URL bez ostrzeżenia. Ale nadal uważam, że należy to naprawić. Jeśli chcesz
rzucić
3

Natrafiłem na ten sam problem i okazało się, że odwrotne dns nie było poprawnie ustawione, wskazywało to na niewłaściwą nazwę hosta dla adresu IP. Po poprawieniu odwrotnej usługi DNS i ponownym uruchomieniu httpd ostrzeżenie zniknęło. (jeśli nie poprawię odwrotnego dns, dodanie ServerName również załatwiło sprawę)

użytkownik 2888387
źródło
2

My VirtualHost„s ServerNamezostał wykomentowane domyślnie. Działa po odkomentowaniu.

Aram Paronikyan
źródło
To samo tutaj. Brak nazwy serwera.
Dark Star 1
2

Jeśli budujesz klienta za pomocą Resttemplate, możesz ustawić tylko punkt końcowy w następujący sposób: https: // IP / ścieżka_do_usługi i ustawić parametr requestFactory.
Dzięki temu rozwiązaniu nie musisz PONOWNIE uruchamiać TOMCAT lub Apache:

public static HttpComponentsClientHttpRequestFactory requestFactory(CloseableHttpClient httpClient) {
    TrustStrategy acceptingTrustStrategy = new TrustStrategy() {
        @Override
        public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            return true;
        }
    };

    SSLContext sslContext = null;
    try {
        sslContext = org.apache.http.ssl.SSLContexts.custom()
                .loadTrustMaterial(null, acceptingTrustStrategy)
                .build();
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
    }   

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

    final SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext,hostnameVerifier);

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

    final PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
    cm.setMaxTotal(100);
    httpClient = HttpClients.custom()
            .setSSLSocketFactory(csf)
            .setConnectionManager(cm)
            .build();

    HttpComponentsClientHttpRequestFactory requestFactory =
            new HttpComponentsClientHttpRequestFactory();

    requestFactory.setHttpClient(httpClient);

    return requestFactory;
}
Alfredo
źródło
1

Natknąłem się również na ten problem podczas aktualizacji z Java 1.6_29 do 1.7.

Niepokojące jest to, że mój klient odkrył ustawienie w panelu sterowania Java, które to rozwiązuje.

W zakładce Zaawansowane możesz zaznaczyć „Użyj zgodnego z SSL 2.0 formatu ClientHello”.

To wydaje się rozwiązać problem.

Korzystamy z apletów Java w przeglądarce Internet Explorer.

Mam nadzieję że to pomoże.

Allan D.
źródło
0

Miałem ten sam problem z serwerem Ubuntu Linux z uruchomioną wersją subversion, gdy dostęp do niego odbywa się za pośrednictwem Eclipse.

Pokazało, że problem miał związek z ostrzeżeniem, gdy uruchomiono (ponownie) Apache:

[Mon Jun 30 22:27:10 2014] [warn] NameVirtualHost *:80 has no VirtualHosts

... waiting [Mon Jun 30 22:27:11 2014] [warn] NameVirtualHost *:80 has no VirtualHosts

Wynika to z nowego wpisu w ports.conf, w którym NameVirtualHostobok dyrektywy wprowadzono kolejną dyrektywę sites-enabled/000-default.

Po usunięciu dyrektywy ports.confproblem zniknął (oczywiście po ponownym uruchomieniu Apache)

Gerhard
źródło
0

Aby dodać rozwiązanie tutaj. Może to pomóc użytkownikom LAMP

Options +FollowSymLinks -SymLinksIfOwnerMatch

Winowajcą była wyżej wymieniona linia w konfiguracji wirtualnego hosta.

Konfiguracja hosta wirtualnego, gdy wystąpi błąd

<VirtualHost *:80>
    DocumentRoot /var/www/html/load/web
    ServerName dev.load.com
    <Directory "/var/www/html/load/web">
        Options +FollowSymLinks -SymLinksIfOwnerMatch
        AllowOverride All
        Require all granted
        Order Allow,Deny
        Allow from All
    </Directory>
     RewriteEngine on
     RewriteCond %{SERVER_PORT} !^443$
     RewriteRule ^/(.*) https://%{HTTP_HOST}/$1 [NC,R=301,L]
</VirtualHost>

Konfiguracja robocza

<VirtualHost *:80>
    DocumentRoot /var/www/html/load/web

   ServerName dev.load.com
   <Directory "/var/www/html/load/web">

        AllowOverride All

        Options All

        Order Allow,Deny

        Allow from All

    </Directory>

    # To allow authorization header
    RewriteEngine On
    RewriteCond %{HTTP:Authorization} ^(.*)
    RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]

   # RewriteCond %{SERVER_PORT} !^443$
   # RewriteRule ^/(.*) https://%{HTTP_HOST}/$1 [NC,R=301,L]


</VirtualHost>
Gryf
źródło
0

Oto rozwiązanie dla Appache httpclient 4.5.11. Miałem problem z certyfikatem, który poddał wildcard *.hostname.com. Zwrócił mi ten sam wyjątek, ale nie mogłem używać wyłączania według właściwości, System.setProperty("jsse.enableSNIExtension", "false");ponieważ popełnił błąd w kliencie lokalizacji Google.

Znalazłem proste rozwiązanie (tylko gniazdo modyfikujące):

import io.micronaut.context.annotation.Bean;
import io.micronaut.context.annotation.Factory;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;

import javax.inject.Named;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import java.io.IOException;
import java.util.List;

@Factory
public class BeanFactory {

    @Bean
    @Named("without_verify")
    public HttpClient provideHttpClient() {
        SSLConnectionSocketFactory connectionSocketFactory = new SSLConnectionSocketFactory(SSLContexts.createDefault(), NoopHostnameVerifier.INSTANCE) {
            @Override
            protected void prepareSocket(SSLSocket socket) throws IOException {
                SSLParameters parameters = socket.getSSLParameters();
                parameters.setServerNames(List.of());
                socket.setSSLParameters(parameters);
                super.prepareSocket(socket);
            }
        };

        return HttpClients.custom()
                .setSSLSocketFactory(connectionSocketFactory)
                .build();
    }


}
Andrew Sneck
źródło
-1

Jest łatwiejszy sposób którym możesz po prostu użyć własnego HostnameVerifier do niejawnego zaufania do niektórych połączeń. Problem występuje w Javie 1.7, w której dodano rozszerzenia SNI, a twój błąd jest spowodowany błędną konfiguracją serwera.

Możesz użyć opcji „-Djsse.enableSNIExtension = false”, aby wyłączyć SNI w całej maszynie JVM, lub przeczytać mój blog, w którym wyjaśniam, jak zaimplementować niestandardowy weryfikator na podstawie połączenia URL.

MagicDude4Eva
źródło