SSL 핸드 셰이크 경고 : Java 1.7.0으로 업그레이드 한 후 unrecognized_name 오류


225

오늘 Java 1.6에서 Java 1.7로 업그레이드했습니다. 그 이후 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)

코드는 다음과 같습니다.

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

코드와 함께 신뢰할 수없는 인증서를 허용하고 사용하는 이유는 테스트 프로젝트뿐입니다.

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

https://google.com 에 연결하려고했습니다 . 내 잘못은 어디에 있습니까?

감사.

답변:


304

Java 7에는 기본적으로 활성화 된 SNI 지원이 도입되었습니다. 잘못 구성된 일부 서버는 SSL 핸드 셰이크에서 "인식 할 수없는 이름"경고를 보내며 이는 대부분의 클라이언트가 무시합니다 (Java 제외). 으로 @Bob 컨스가 언급 한 오라클 엔지니어들은이 버그 / 기능 "수정"을 거부한다.

이 문제를 해결하려면 jsse.enableSNIExtension속성 을 설정하는 것이 좋습니다 . 다시 컴파일하지 않고 프로그램을 작동 시키려면 앱을 다음과 같이 실행하십시오.

java -Djsse.enableSNIExtension=false yourClass

이 속성은 Java 코드에서 설정할 수도 있지만 SSL 작업 전에 설정해야합니다 . SSL 라이브러리가로드되면 특성을 변경할 수 있지만 SNI 상태에는 영향미치지 않습니다 . 런타임시 SNI를 비활성화하려면 (위에서 언급 한 제한 사항이 있음) 다음을 사용하십시오.

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

이 플래그 설정의 단점은 SNI가 응용 프로그램의 모든 곳에서 사용 불가능하다는 것입니다. SNI를 사용하고 여전히 잘못 구성된 서버를 지원하려면 다음을 수행하십시오.

  1. SSLSocket연결하려는 호스트 이름으로를 작성하십시오 . 이 이름을 지정합시다 sslsock.
  2. 실행 해보십시오 sslsock.startHandshake(). 완료 될 때까지 차단되거나 오류시 예외가 발생합니다. 에서 오류가 발생할 때마다 startHandshake()예외 메시지가 표시됩니다. 이 (가)이면 handshake alert: unrecognized_name잘못 구성된 서버를 발견 한 것입니다.
  3. unrecognized_name경고 (Java에서 치명적)를 수신하면 SSLSocket호스트 이름 없이을 다시 시도하십시오 . 이렇게하면 SNI가 효과적으로 비활성화됩니다. 결국 SNI 확장은 ClientHello 메시지에 호스트 이름을 추가하는 것입니다.

Webscarab SSL 프록시의 경우이 커밋 은 대체 설정을 구현합니다.


5
작동합니다, 감사합니다! HTTPS를 통해 연결할 때 IntelliJ IDEA 서브 버전 클라이언트에서 동일한 오류가 발생했습니다. idea.exe.vmoptions 파일을 다음 줄로 업데이트하면됩니다. -Djsse.enableSNIExtension = false
Dima

2
java webstart의 경우 다음을 사용하십시오. javaws -J-Djsse.enableSNIExtension = false yourClass
Torsten

https 나머지 서버가있는 Jersey 클라이언트와 똑같은 문제가있었습니다. 내가 당신의 트릭을 사용한 것으로 나타났습니다. 감사!
shahshi15

4
Java 8에 대해 궁금해하는 사람들을 위해 Oracle은 여전히 ​​동작을 변경하지 않았으며 프로그래머가 SNI를 (적절하게) 지원하지 않는 서버를 잡도록 요구합니다. docs.oracle.com/javase/8/docs/technotes/guides/security/jsse
Lekensteyn

2
@Blauhirn 웹 호스트 지원 센터에 문의하십시오. 구성을 수정해야합니다. 이들이 Apache를 사용하는 경우 변경해야 할 사항이 있는지 살펴보십시오.
Lekensteyn

89

나는 똑같은 문제가 있다고 생각했습니다. 호스트의 ServerName 또는 ServerAlias를 포함하도록 Apache 구성을 조정해야한다는 것을 알았습니다.

이 코드는 실패했습니다 :

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

그리고이 코드는 작동했습니다 :

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는 TSL / SSL Hello 중에 경고 경고 (수준 : 경고, 설명 : 인식 할 수없는 이름), 서버 Hello가 서버에서 클라이언트로 전송되고 있음을 공개했습니다. 그러나 Java 7.1은 "치명적, 설명 : 예상치 못한 메시지"로 즉시 응답했습니다. Java SSL 라이브러리가 인식 할 수없는 이름의 경고를보고 싶지 않다는 것을 의미합니다.

TLS (Transport Layer Security) 위키에서 :

112 인식 할 수없는 이름 경고 TLS 만 해당; 클라이언트의 서버 이름 표시기가 서버에서 지원하지 않는 호스트 이름을 지정했습니다.

이로 인해 Apache 구성 파일을 보았고 클라이언트 / 자바 측에서 보낸 이름으로 ServerName 또는 ServerAlias를 추가하면 오류없이 올바르게 작동한다는 것을 알았습니다.

<VirtualHost mydomain.com:443>
  ServerName mydomain.com
  ServerAlias www.mydomain.com

3
이것은 Java TLS 구현의 버그처럼 보입니다.
Paŭlo Ebermann 2018

1
나는 실제로 이것에 대한 버그를 openend합니다. 이 번호가 지정되었지만 아직 표시되지 않았습니다. bugs.sun.com/bugdatabase/view_bug.do?bug_id=7127374
eckes

1
고마워, ServerAlias나를 위해 일한 추가 . Wireshark에서 동일한 TLS 경고를 보았습니다.
Jared Beck

2
이것은 또한 나를 위해 일했습니다. (내가 그것을 믿고 다른 길을 찾아 가지 않았다면 더 잘 작동했을 것이다)
최종 사용자

10
@JosephShraibman, 오라클 직원이 바보라고 말하면 부적절합니다. 둘을 사용할 때ServerName Apache는 unrecognized_name 경고 경고 ( 치명적 경고 일 수도 있음)로 응답합니다 . RFC 6066 은이 주제에 대해 다음과 같이 정확하게 말합니다. " 경고 수준 경고에 대한 클라이언트의 동작을 예측할 수 없기 때문에 경고 수준 unrecognized_name (112) 경고를 보내는 것은 권장되지 않습니다. ". 이 직원의 유일한 실수는 이것이 치명적인 경고 라고 가정하는 것 입니다. 이것은 아파치 버그만큼 JRE 버그입니다.
Bruno

36

시스템 특성 jsse.enableSNIExtension = false를 사용하여 SNI 레코드 전송을 비활성화 할 수 있습니다.

코드를 변경할 수 있으면 사용하는 데 도움이됩니다 SSLCocketFactory#createSocket()(호스트 매개 변수가 없거나 연결된 소켓이 있음). 이 경우 server_name 표시를 보내지 않습니다.


11
다음과 같이 수행됩니다.System.setProperty ("jsse.enableSNIExtension", "false");
jn1kk

나는 그것이 항상 작동하지 않는 것을 발견했다. 왜 어떤 경우에는 작동하는지, 다른 경우에는 작동하지 않습니다.
Joseph Shraibman

2
와 함께 작동합니다 -Djsse.enableSNIExtension=false. 그러나 또 다른 일은 무엇입니까? 나머지 Java 보안에 유해합니까?
ceving

2
공유 IP 뒤에서 여러 호스트 이름을 사용하는 일부 사이트 (특히 웹 서버)가 어떤 인증서를 보내야하는지 알 수 없습니다. 그러나 Java 앱이 수백만 개의 웹 사이트에 연결되어 있지 않으면 해당 기능이 필요하지 않습니다. 이러한 서버가 발생하면 인증서 유효성 검사가 실패하고 연결이 중단 될 수 있습니다. 따라서 예상되는 보안 문제는 없습니다.
eckes

17

또한 새로운 Apache 서버 빌드에서이 오류가 발생했습니다.

우리의 경우 수정은 Java가 연결하려고 시도한 호스트 이름에 해당 하는를 정의하는 것 ServerAlias입니다 httpd.conf. 우리 ServerName는 내부 호스트 이름으로 설정되었습니다. SSL 인증서가 외부 호스트 이름을 사용하고 있었지만 경고를 피하기에는 충분하지 않았습니다.

디버그를 돕기 위해이 ssl 명령을 사용할 수 있습니다.

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

해당 호스트 이름에 문제가 있으면 출력 상단 근처에이 메시지가 인쇄됩니다.

SSL3 alert read: warning:unrecognized name

또한 SSL 인증서와 일치하지 않더라도 해당 명령을 사용하여 내부 호스트 이름에 연결할 때 해당 오류가 발생하지 않았습니다.


6
를 사용하여 문제를 재현하는 방법에 대한 예를 포함 해 주셔서 감사합니다 openssl. 매우 도움이됩니다.
sideshowbarker

2
openssl 클라이언트가 메시지의 이름 차이를 볼 수있는 방법이 SSL3 alert read: warning:unrecognized name있습니까? 나는 경고가 인쇄 볼 수 있지만 출력은 실제로이 이름의 차이를보고 나에게 도움이되지 않습니다
mox601

이것은 나를 위해 작동하지 않습니다. 테스트 OpenSSL 1.0.1e-fips 11 Feb 2013, OpenSSL 1.0.2k-fips 26 Jan 2017LibreSSL 2.6.5.
Greg Dubicki '10

15

아파치의 기본 가상 호스트 메커니즘에 의존하는 대신 임의의 ServerName과 와일드 카드 ServerAlias를 사용하는 마지막 catchall 가상 호스트를 정의 할 수 있습니다.

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

이런 식으로 SNI를 사용할 수 있으며 Apache는 SSL 경고를 다시 보내지 않습니다.

물론 이것은 와일드 카드 구문을 사용하여 모든 도메인을 쉽게 설명 할 수있는 경우에만 작동합니다.


내가 아는 한 아파치는 클라이언트가 ServerName 또는 ServerAlias로 구성되지 않은 이름을 사용하는 경우에만이 경고를 보냅니다. 따라서 와일드 카드 인증서가있는 경우 사용 된 모든 하위 도메인을 지정하거나 *.mydomain.comServerAlias ​​구문을 사용하십시오 . 참고 사용 여러 개의 별칭을 추가 할 수 있습니다 ServerAlias예를 들어, ServerAlias *.mydomain.com mydomain.com *.myotherdomain.com.
Michael Paesold

13

유용해야합니다. Apache HttpClient 4.4에서 SNI 오류를 다시 시도하려면 가장 쉬운 방법입니다 ( 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;
            }
        }
    }
}

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

cm = new PoolingHttpClientConnectionManager(new SniHttpClientConnectionOperator(socketFactoryRegistry), null, -1, TimeUnit.MILLISECONDS);

이렇게하면 당신은 어떻게 대처합니까 verifyHostname(sslsock, target)에서 SSLConnectionSocketFactory.createLayeredSocket? (가)부터 target빈 문자열로 변경, verifyHostname성공 않을 것입니다. 여기에 명백한 것이 빠져 있습니까?
Haozhun

2
이것은 내가 찾던 것입니다. 정말 감사합니다! 이 "unrecognized_name"경고로 동시에 응답하는 SNI 및 서버를 지원하는 다른 방법을 찾지 못했습니다.
korpe

이 솔루션은 프록시 서버를 사용하지 않는 한 작동합니다.
mrog

verifyHostname ()으로 시작하여 Apache 클라이언트 코드를 통해 빠른 디버그를 수행 한 후 DefaultHostnameVerifier를 사용하여 이것이 어떻게 작동하는지 알 수 없습니다. 이 솔루션에서 호스트 이름 확인을 비활성화해야한다고 생각합니다 (예 : NoopHostnameVerifier 사용). 중간자 공격을 허용하는 것은 좋지 않습니다.
FlyingSheep


6

스프링 부 트로이 문제에 부딪 쳤습니다. 및 jvm 1.7 및 1.8 . AWS에서는 ServerName과 ServerAlias를 일치하도록 변경할 수있는 옵션이 없었으므로 다음과 같이했습니다.

에서 build.gradle 우리는 다음을 추가 :

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

이를 통해 "인식 할 수없는 이름"문제를 우회 할 수있었습니다.


5

불행히도 jarsigner.exe 도구에 시스템 특성을 제공 할 수 없습니다.

나는 결함 제출 한 7,177,232 , @eckes '결함 참조 7,127,374을 하고 그것이 오류가 폐쇄 된 이유를 설명합니다.

내 결함은 특히 jarsigner 도구에 미치는 영향에 관한 것이지만 다른 결함을 다시 열어 문제를 올바르게 해결할 수 있습니다.

업데이트 : 실제로 Jarsigner 도구에 시스템 속성을 제공 할 수 있다는 것이 밝혀졌습니다. 도움말 메시지에는 없습니다. 사용하다jarsigner -J-Djsse.enableSNIExtension=false


1
후속 감사합니다. 슬프게도 오라클은 여전히 ​​모든 것을 이해하지 못합니다. SNI 경고는 치명적이지 않으며 치명적일 수 있습니다. 그러나 가장 일반적인 SSL 클라이언트 (예 : 브라우저)는 실제 보안 문제가 아니므로 서버 인증서를 확인해야하고 잘못된 끝점을 감지하기 때문에이를 무시하기로 선택했습니다. 물론 CA가 설정할 수없는 것은 슬픈 일입니다 올바르게 구성된 https 서버를 설정하십시오.
eckes

2
실제로 Jarsigner 도구에 시스템 특성을 제공 할 수 있으며 도움말 메시지에는 포함되지 않습니다. 설명서에서 다룹니다. 온라인 텍스트를 믿어 주셔서 감사합니다. 물론 그들은 이것을 고치지 않은 변명으로 사용했습니다.
Bob Kerns

BTW : 현재 security-dev @ openjdk에서이 문제에 대해 논의 중이며 시만텍이 GEOTrust 타임 스탬프 서버를 수정 한 것으로 보이는 시점에 경고없이 URL을 올바르게 수락합니다. 그러나 나는 여전히 그 문제를 해결해야한다고 생각합니다. 살펴보고 싶다면, 테스트 클라이언트 프로젝트와 토론 :
eckes

3

나는 같은 문제에 부딪 쳤고 역방향 DNS가 올바르게 설정되지 않았으며 IP의 잘못된 호스트 이름을 지적했습니다. 역방향 DNS를 수정하고 httpd를 다시 시작하면 경고가 사라집니다. (역 DNS를 수정하지 않으면 ServerName을 추가해도 나에게 속임수를 썼습니다)



2

Resttemplate을 사용하여 클라이언트를 빌드하는 경우 https : // IP / path_to_service 와 같은 엔드 포인트 만 설정하고 requestFactory를 설정할 수 있습니다.
이 솔루션을 사용하면 TOMCAT 또는 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;
}

1

Java 1.6_29에서 1.7로 업그레이드하는 동안이 문제가 발생했습니다.

놀랍게도, 고객이 Java 제어판에서이를 해결하는 설정을 발견했습니다.

고급 탭에서 'SSL 2.0 호환 ClientHello 형식 사용'을 확인할 수 있습니다.

이것은 문제를 해결하는 것으로 보입니다.

Internet Explorer 브라우저에서 Java 애플릿을 사용하고 있습니다.

도움이 되었기를 바랍니다.


0

Eclipse를 통해 액세스 할 때 Subversion을 실행하는 Ubuntu Linux 서버와 동일한 문제가있었습니다.

아파치 (재)가 시작될 때 문제는 경고와 관련이있는 것으로 나타났습니다 :

[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

의에 새 항목이 추가 되었기 때문에에 ports.conf다른 NameVirtualHost지시문과 함께 지시문이 입력되었습니다 sites-enabled/000-default.

에서 지시문을 제거한 후 ports.conf문제가 사라졌습니다 (아파치를 다시 시작한 후 자연스럽게).


0

여기에 솔루션을 추가하십시오. 이것은 램프 사용자에게 도움이 될 수 있습니다

Options +FollowSymLinks -SymLinksIfOwnerMatch

가상 호스트 구성에서 위에서 언급 한 행이 원인입니다.

오류 발생시 가상 호스트 구성

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

작업 구성

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

0

다음은 Appache httpclient 4.5.11에 대한 솔루션입니다. 와일드 카드를 사용하는 인증서에 문제가있었습니다 *.hostname.com. 동일한 예외가 반환되었지만 System.setProperty("jsse.enableSNIExtension", "false");Google 위치 클라이언트에서 오류가 발생했기 때문에 속성별로 사용 ​​중지하지 않아야합니다 .

간단한 해결책을 찾았습니다 (수정 소켓 만).

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


}

-1

고유 한 HostnameVerifier를 사용하여 특정 연결을 암시 적으로 신뢰할 수 있는 더 쉬운 방법 이 있습니다. 이 문제는 SNI 확장이 추가 된 Java 1.7에서 발생하며 오류는 서버 구성 오류로 인한 것입니다.

"-Djsse.enableSNIExtension = false"를 사용하여 전체 JVM에서 SNI를 비활성화하거나 URL 연결 위에 사용자 지정 검증기를 구현하는 방법을 설명하는 내 블로그를 읽을 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.