Peringatan jabat tangan SSL: kesalahan nama yang tidak dikenal sejak peningkatan ke Java 1.7.0

225

Saya memutakhirkan dari Java 1.6 ke Java 1.7 hari ini. Sejak itu terjadi kesalahan ketika saya mencoba membuat koneksi ke server web saya melalui 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)

Ini kodenya:

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

Ini hanya proyek pengujian, itulah sebabnya saya mengizinkan dan menggunakan sertifikat yang tidak dipercaya dengan kode:

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

Saya berhasil mencoba terhubung ke https://google.com . dimana salahku?

Terima kasih.

pvomhoff
sumber

Jawaban:

304

Java 7 memperkenalkan dukungan SNI yang diaktifkan secara default. Saya telah menemukan bahwa beberapa server yang salah konfigurasi mengirimkan peringatan "Nama Tidak Dikenal" di jabat tangan SSL yang diabaikan oleh sebagian besar klien ... kecuali untuk Java. Seperti @Bob Kerns sebutkan, para insinyur Oracle menolak untuk "memperbaiki" bug / fitur ini.

Sebagai solusi, mereka menyarankan untuk mengatur jsse.enableSNIExtensionproperti. Agar program Anda berfungsi tanpa kompilasi ulang, jalankan aplikasi Anda sebagai:

java -Djsse.enableSNIExtension=false yourClass

Properti juga dapat diatur dalam kode Java, tetapi harus diatur sebelum tindakan SSL apa pun . Setelah pustaka SSL memuat, Anda dapat mengubah properti, tetapi tidak akan berpengaruh pada status SNI . Untuk menonaktifkan SNI saat runtime (dengan batasan yang disebutkan di atas), gunakan:

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

Kerugian dari pengaturan tanda ini adalah bahwa SNI dinonaktifkan di mana-mana dalam aplikasi. Untuk menggunakan SNI dan masih mendukung server yang salah konfigurasi:

  1. Buat SSLSocketdengan nama host yang ingin Anda sambungkan. Sebutkan ini sslsock.
  2. Coba lari sslsock.startHandshake(). Ini akan memblokir sampai selesai atau membuat pengecualian kesalahan. Setiap kali kesalahan terjadi startHandshake(), dapatkan pesan pengecualian. Jika sama dengan handshake alert: unrecognized_name, maka Anda telah menemukan server yang salah konfigurasi.
  3. Ketika Anda telah menerima unrecognized_nameperingatan (fatal di Jawa), coba ulangi pembukaan SSLSocket, tetapi kali ini tanpa nama host. Ini secara efektif menonaktifkan SNI (setelah semua, ekstensi SNI adalah tentang menambahkan nama host ke pesan ClientHello).

Untuk proksi SSL Webscarab, komitmen ini mengimplementasikan pengaturan mundur.

Lekensteyn
sumber
5
itu berhasil, terima kasih! Klien subversi IntelliJ IDEA memiliki kesalahan yang sama saat menghubungkan melalui HTTPS. Hanya perlu memperbarui file idea.exe.vmoptions dengan baris: -Djsse.enableSNIExtension = false
Dima
2
Untuk java webstart gunakan ini: javaws -J-Djsse.enableSNIExtension = false yourClass
Torsten
Saya memiliki masalah yang sama persis dengan klien Jersey saya dengan server sisanya https. Ternyata saya menggunakan trik Anda dan itu berhasil !! Terima kasih!
shahshi15
4
Bagi mereka yang bertanya-tanya tentang Java 8, Oracle masih belum mengubah perilaku dan masih meminta programmer untuk menangkap server yang tidak (dengan benar) mendukung SNI: docs.oracle.com/javase/8/docs/technotes/guides/security/jsse / ...
Lekensteyn
2
@ Blauhirn Hubungi dukungan hosting Anda, mereka harus memperbaiki konfigurasinya. Jika mereka menggunakan Apache, lihat ke bawah untuk beberapa perubahan yang perlu dilakukan.
Lekensteyn
89

Saya memiliki apa yang saya yakini masalah yang sama. Saya menemukan bahwa saya perlu menyesuaikan konfigurasi Apache untuk memasukkan ServerName atau ServerAlias ​​untuk host.

Kode ini gagal:

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

Dan kode ini berfungsi:

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 mengungkapkan bahwa selama TSL / SSL Hello Alert peringatan (Level: Peringatan, Deskripsi: Nama Tidak Dikenali), Server Hello sedang dikirim dari server ke klien. Itu hanya peringatan, namun, Java 7.1 kemudian segera merespons kembali dengan "Fatal, Deskripsi: Pesan Tak Terduga", yang saya anggap berarti perpustakaan SSL Java tidak suka melihat peringatan nama yang tidak dikenal.

Dari Wiki di Transport Layer Security (TLS):

112 Hanya TLS peringatan nama yang tidak dikenal; Indikator Nama Server klien menentukan nama host yang tidak didukung oleh server

Ini mengarahkan saya untuk melihat file konfigurasi Apache saya dan saya menemukan bahwa jika saya menambahkan ServerName atau ServerAlias ​​untuk nama yang dikirim dari sisi klien / java, itu berfungsi dengan benar tanpa kesalahan.

<VirtualHost mydomain.com:443>
  ServerName mydomain.com
  ServerAlias www.mydomain.com
David McLaughlin
sumber
3
Ini terlihat seperti bug dalam implementasi TLS Java.
Paŭlo Ebermann
1
Saya sebenarnya membuka bug untuk ini. Saya mendapat nomor ini (belum terlihat): bugs.sun.com/bugdatabase/view_bug.do?bug_id=7127374
eckes
1
Terima kasih, menambahkan yang ServerAliasberfungsi untuk saya. Saya telah melihat peringatan TLS yang sama di Wireshark.
Jared Beck
2
Ini berhasil juga untuk saya. (akan bekerja lebih baik jika saya percaya dan tidak pergi memburu jalan lain)
pengguna akhir
10
@ JosephShraibman, mengatakan karyawan Oracle itu idiot tidak pantas. Ketika Anda menggunakan dua ServerNames, Apache merespons dengan unrecognized_name peringatan (yang juga bisa menjadi peringatan fatal ). RFC 6066 dengan tepat mengatakan ini pada topik ini: " TIDAK DIREKOMENDASIKAN untuk mengirimkan peringatan tingkat-tingkat yang tidak dikenal (112), karena perilaku klien dalam menanggapi peringatan tingkat peringatan tidak dapat diprediksi. ". Satu-satunya kesalahan yang dilakukan oleh karyawan ini adalah menganggap bahwa ini adalah peringatan fatal . Ini adalah bug JRE sama seperti bug Apache.
Bruno
36

Anda dapat menonaktifkan pengiriman catatan SNI dengan properti System jsse.enableSNIExtension = false.

Jika Anda dapat mengubah kode, sebaiknya gunakan SSLCocketFactory#createSocket()(tanpa parameter host atau dengan soket yang terhubung). Dalam hal ini tidak akan mengirim indikasi server_name.

eckes
sumber
11
Yang dilakukan seperti ini:System.setProperty ("jsse.enableSNIExtension", "false");
jn1kk
Saya menemukan bahwa itu tidak selalu berhasil. Saya tidak tahu mengapa itu bekerja dalam beberapa kasus dan tidak pada yang lain.
Joseph Shraibman
2
Bekerja untuk saya -Djsse.enableSNIExtension=false. Tapi apa lagi fungsinya? Apakah itu berbahaya bagi keamanan Jawa lainnya?
ceving
2
Tidak, itu hanya berarti bahwa beberapa situs (terutama server web) yang menggunakan nama host mutiple di belakang IP bersama tidak tahu sertifikat apa yang harus dikirim. Tetapi kecuali aplikasi java Anda harus terhubung ke jutaan situs web Anda tidak perlu fitur itu. Jika Anda menemukan server seperti itu, validasi sertifikat Anda mungkin gagal dan koneksi dibatalkan. Jadi tidak ada masalah keamanan yang diharapkan.
eckes
17

Kami juga mengalami kesalahan ini pada build server Apache baru.

Memperbaiki dalam kasus kami adalah untuk mendefinisikan ServerAliasdi httpd.confyang sesuai dengan nama host yang mencoba terhubung ke Jawa. Kami ServerNameditetapkan ke nama host internal. Sertifikat SSL kami menggunakan nama host eksternal, tetapi itu tidak cukup untuk menghindari peringatan.

Untuk membantu debug, Anda dapat menggunakan perintah ssl ini:

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

Jika ada masalah dengan nama host itu, maka itu akan mencetak pesan ini di dekat bagian atas output:

SSL3 alert read: warning:unrecognized name

Saya juga harus mencatat bahwa kami tidak mendapatkan kesalahan itu ketika menggunakan perintah itu untuk terhubung ke nama host internal, meskipun itu tidak cocok dengan sertifikat SSL.

Scott McIntyre
sumber
6
Terima kasih telah menyertakan contoh tentang cara mereproduksi masalah menggunakan openssl. Ini sangat membantu.
sontonbarker
2
Apakah ada cara bagi klien openssl untuk melihat perbedaan nama yang berasal dari pesan SSL3 alert read: warning:unrecognized name? Saya melihat lansiran dicetak, tetapi hasilnya tidak membantu saya untuk benar-benar melihat perbedaan penamaan ini
mox601
Ini tidak berhasil untuk saya. Diuji dengan OpenSSL 1.0.1e-fips 11 Feb 2013, OpenSSL 1.0.2k-fips 26 Jan 2017dan LibreSSL 2.6.5.
Greg Dubicki
15

Alih-alih mengandalkan mekanisme host virtual default di apache, Anda dapat menentukan satu virtualhost catchall terakhir yang menggunakan ServerName sewenang-wenang dan wildcard ServerAlias, misalnya

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

Dengan cara itu Anda dapat menggunakan SNI dan apache tidak akan mengirim kembali peringatan SSL.

Tentu saja, ini hanya berfungsi jika Anda dapat menggambarkan semua domain Anda dengan mudah menggunakan sintaks wildcard.

Erik
sumber
Sejauh yang saya mengerti, apache hanya mengirimkan peringatan ini jika klien menggunakan nama yang tidak dikonfigurasi sebagai ServerName atau ServerAlias. Jadi jika Anda memiliki sertifikat kartu liar, tentukan semua sub domain yang digunakan, atau gunakan *.mydomain.comsintaks untuk ServerAlias. Perhatikan bahwa Anda dapat menambahkan beberapa alias menggunakan ServerAlias, misalnya ServerAlias *.mydomain.com mydomain.com *.myotherdomain.com.
Michael Paesold
13

Itu harus bermanfaat. Untuk mencoba lagi kesalahan SNI di Apache HttpClient 4.4 - cara termudah yang kami buat (lihat 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;
            }
        }
    }
}

dan

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

dan

cm = new PoolingHttpClientConnectionManager(new SniHttpClientConnectionOperator(socketFactoryRegistry), null, -1, TimeUnit.MILLISECONDS);
Shcheklein
sumber
Jika Anda melakukannya dengan cara ini. Bagaimana Anda menangani verifyHostname(sslsock, target)di SSLConnectionSocketFactory.createLayeredSocket? Karena targetdiubah menjadi string kosong, verifyHostnametidak akan berhasil. Apakah saya melewatkan sesuatu yang jelas di sini?
Haozhun
2
Ini tepatnya, apa yang saya cari, terima kasih banyak! Saya tidak menemukan cara lain untuk mendukung SNI dan server yang merespons dengan peringatan "tidak dikenal" ini secara bersamaan.
korpe
Solusi ini berfungsi, kecuali jika Anda menggunakan server proxy.
mrog
Setelah baru saja melakukan debug cepat melalui kode klien Apache, dimulai dengan memverifikasiHostname (), saya tidak dapat melihat bagaimana ini dapat bekerja menggunakan DefaultHostnameVerifier. Saya menduga bahwa solusi ini memerlukan verifikasi Hostname untuk dinonaktifkan (misalnya menggunakan NoopHostnameVerifier), yang BUKAN ide yang baik karena memungkinkan serangan man-in-the-middle.
FlyingSheep
11

Menggunakan:

  • System.setProperty ("jsse.enableSNIExtension", "false");
  • Mulai ulang Tomcat Anda (penting)
Tomasz Janisiewicz
sumber
6

Mengalami masalah ini dengan spring boot dan jvm 1.7 dan 1.8. Pada AWS, kami tidak memiliki opsi untuk mengubah ServerName dan ServerAlias ​​agar sesuai (mereka berbeda) sehingga kami melakukan yang berikut:

Di build.gradle kami menambahkan yang berikut:

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

Itu memungkinkan kami untuk mengatasi masalah dengan "Nama Tidak Dikenal".

Ray Hunter
sumber
5

Sayangnya, Anda tidak dapat memasok properti sistem ke alat jarsigner.exe.

Saya telah mengirimkan defect 7177232 , mereferensikan defect @eckes 7127374 dan menjelaskan mengapa itu ditutup karena kesalahan.

Cacat saya secara khusus tentang dampak pada alat jarsigner, tapi mungkin itu akan menyebabkan mereka membuka kembali cacat lainnya dan mengatasi masalah dengan benar.

PEMBARUAN: Sebenarnya, Anda BISA memasok properti sistem ke alat Jarsigner, hanya saja tidak ada dalam pesan bantuan. Menggunakanjarsigner -J-Djsse.enableSNIExtension=false

Bob Kerns
sumber
1
Terima kasih Bob atas tindak lanjutnya. Sayangnya Oracle masih belum mengerti semuanya. Tanda SNI tidak fatal, dapat berakibat fatal. Tetapi kebanyakan klien SSL biasa (yaitu browser) memilih untuk mengabaikannya karena itu bukan masalah keamanan nyata (karena Anda masih perlu memeriksa sertifikat server dan akan mendeteksi titik akhir yang salah). Tentu saja sedih bahwa CA tidak dapat mengatur server https yang dikonfigurasi dengan benar.
eckes
2
Sebenarnya, ternyata Anda BISA memasok properti sistem ke alat Jarsigner, hanya saja tidak ada dalam pesan bantuan. Itu tercakup dalam dokumentasi. Bodoh saya karena percaya teks online. Tentu saja, mereka menggunakan ini sebagai alasan untuk tidak memperbaikinya.
Bob Kerns
BTW: Saat ini saya sedang membahas masalah ini pada security-dev @ openjdk dan saat ini saya mengevaluasinya sepertinya Symantec memperbaiki server timestamping GEOTrust, sekarang dengan benar menerima URL tanpa peringatan. Tapi saya masih berpikir itu harus diperbaiki. Jika Anda ingin melihat-lihat, proyek klien pengujian dan diskusi :
eckes
3

Saya mengalami masalah yang sama dan ternyata reverse dns tidak diatur dengan benar, itu menunjuk ke nama host yang salah untuk IP. Setelah saya memperbaiki dns terbalik dan memulai kembali httpd, peringatan itu hilang. (jika saya tidak memperbaiki dns terbalik, menambahkan ServerName juga membantu saya)

pengguna2888387
sumber
2

Saya VirtualHost's ServerNameitu komentar secara default. Itu bekerja setelah komentar.

Aram Paronikyan
sumber
Sama disini. Nama server tidak ada.
Dark Star1
2

Jika Anda membangun klien dengan Resttemplate, Anda hanya dapat mengatur titik akhir seperti ini: https: // IP / path_to_service dan mengatur requestFactory.
Dengan solusi ini Anda tidak perlu RESTART TOMCAT atau Apache Anda:

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
sumber
1

Saya juga menemukan masalah ini sementara meningkatkan dari Java 1.6_29 ke 1.7.

Yang mengkhawatirkan, pelanggan saya telah menemukan pengaturan di panel kontrol Java yang menyelesaikan ini.

Di Tab Tingkat Lanjut Anda dapat memeriksa 'Gunakan format ClientHello yang kompatibel dengan SSL 2.0'.

Ini sepertinya menyelesaikan masalah.

Kami menggunakan applet Java di browser Internet Explorer.

Semoga ini membantu.

Allan D
sumber
0

Saya memiliki masalah yang sama dengan server Linux Ubuntu menjalankan subversi ketika diakses melalui Eclipse.

Itu telah menunjukkan bahwa masalahnya ada pada peringatan ketika Apache (re) mulai:

[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

Ini karena entri baru ports.conf, di mana NameVirtualHostarahan lain dimasukkan di samping arahan dalam sites-enabled/000-default.

Setelah menghapus arahan dalam ports.conf, masalah telah hilang (setelah me-restart Apache, tentu saja)

Gerhard
sumber
0

Tambahkan saja solusinya di sini. Ini mungkin membantu bagi pengguna LAMP

Options +FollowSymLinks -SymLinksIfOwnerMatch

Baris yang disebutkan di atas dalam konfigurasi virtual host adalah penyebabnya.

Konfigurasi Host Virtual ketika kesalahan

<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>

Konfigurasi Kerja

<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>
Grifon
sumber
0

Berikut ini adalah solusi untuk Appache httpclient 4.5.11. Saya punya masalah dengan cert yang telah ditandai wildcarded *.hostname.com. Itu mengembalikan saya pengecualian yang sama, tapi saya tidak menggunakan penonaktifan oleh properti System.setProperty("jsse.enableSNIExtension", "false");karena itu membuat kesalahan pada klien lokasi Google.

Saya menemukan solusi sederhana (hanya memodifikasi soket):

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
sumber
-1

Ada cara yang lebih mudah di mana Anda bisa menggunakan HostnameVerifier Anda sendiri untuk mempercayai koneksi tertentu secara implisit. Masalahnya datang dengan Java 1.7 di mana ekstensi SNI telah ditambahkan dan kesalahan Anda adalah karena kesalahan konfigurasi server.

Anda dapat menggunakan "-Djsse.enableSNIExtension = false" untuk menonaktifkan SNI di seluruh JVM atau membaca blog saya di mana saya menjelaskan cara menerapkan verifikasi kustom di atas koneksi URL.

MagicDude4Eva
sumber