如何在不禁用 SNI 的情况下修复 SSLProtocolException:握手警报:

我制作了一个爬虫应用程序,由于错误“握手警报:unrecognized_name”,某些网站无法连接。


我发现的大多数解决方案是通过禁用 SNI 扩展 (jsse.enableSNIExtension=false)。但这会给需要启用 SNI 的域带来问题。


我怎样才能只对某些域禁用它?


为了进行爬行,我使用了 Jsoup,并且因为我也在使用代理,所以我在启动时添加了这段代码。


  private static void disableSslVerification() {

    TrustManager[] trustAllCertificates = new TrustManager[] {

            new X509TrustManager() {

                @Override

                public X509Certificate[] getAcceptedIssuers() {

                    return null; // Not relevant.

                }

                @Override

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

                    // Do nothing. Just allow them all.

                }

                @Override

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

                    // Do nothing. Just allow them all.

                }

            }

    };


    HostnameVerifier trustAllHostnames = new HostnameVerifier() {

        @Override

        public boolean verify(String hostname, SSLSession session) {

            return true; // Just allow them all.

        }

    };


    try {

        System.setProperty("https.protocols", "TLSv1.2,TLSv1.1,SSLv3");

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

        SSLContext sc = SSLContext.getInstance("SSL");

        sc.init(null, trustAllCertificates, new SecureRandom());

        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

        HttpsURLConnection.setDefaultHostnameVerifier(trustAllHostnames);

    }

    catch (GeneralSecurityException e) {

        throw new ExceptionInInitializerError(e);

    }

}

如您所见,SNIextension 已被注释。我会很感激一个例子。


我要访问的网址是下一个。


https://www.ocinerioshopping.es/


芜湖不芜
浏览 79回答 1
1回答

慕的地10843

我设法通过扩展 SSLSocketConnection 并在调用 createSocket 时发送 null 而不是主机名来解决问题。这样java就禁用了SNI。然后我只是将新类的一个实例传递给 Jsoup,我知道 SNI 将在其中失败。import javax.net.ssl.*;import java.io.IOException;import java.net.InetAddress;import java.net.Socket;import java.net.UnknownHostException;import java.security.KeyManagementException;import java.security.NoSuchAlgorithmException;import java.security.SecureRandom;import java.security.cert.X509Certificate;public class CustomSSLSocketFactory extends SSLSocketFactory {    private SSLSocketFactory defaultFactory;    public CustomSSLSocketFactory() throws IOException {        TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {            public void checkClientTrusted(X509Certificate[] chain, String authType) {            }            public void checkServerTrusted(X509Certificate[] chain, String authType) {            }            public X509Certificate[] getAcceptedIssuers() {                return null;            }        }};        try {            SSLContext sslContext = SSLContext.getInstance("SSL");            sslContext.init((KeyManager[])null, trustAllCerts, new SecureRandom());            defaultFactory = sslContext.getSocketFactory();        } catch (KeyManagementException | NoSuchAlgorithmException var3) {            throw new IOException("Can't create unsecure trust manager");        }    }    @Override    public String[] getDefaultCipherSuites() {       return defaultFactory.getDefaultCipherSuites();    }    @Override    public String[] getSupportedCipherSuites() {        return defaultFactory.getSupportedCipherSuites();    }    @Override    public Socket createSocket(Socket socket, String s, int i, boolean b) throws IOException {        //magic happens here, we send null as hostname        return defaultFactory.createSocket(socket, null, i, b);    }    @Override    public Socket createSocket(String s, int i) throws IOException, UnknownHostException {        return defaultFactory.createSocket(s,i);    }    @Override    public Socket createSocket(String s, int i, InetAddress inetAddress, int i1) throws IOException, UnknownHostException {        return defaultFactory.createSocket(s,i,inetAddress,i1);    }    @Override    public Socket createSocket(InetAddress inetAddress, int i) throws IOException {        return defaultFactory.createSocket(inetAddress, i);    }    @Override    public Socket createSocket(InetAddress inetAddress, int i, InetAddress inetAddress1, int i1) throws IOException {        return defaultFactory.createSocket(inetAddress,i, inetAddress1, i1);    }}Jsoup 初始化。Connection conn = Jsoup.connect(url);conn.sslSocketFactory(new CustomSSLSocketFactory());
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java