itsource

Apache HttpClient를 사용하여 잘못된 SSL 인증서를 처리하는 방법

mycopycode 2022. 11. 15. 21:40
반응형

Apache HttpClient를 사용하여 잘못된 SSL 인증서를 처리하는 방법

알아요, 이 문제에 대한 많은 질문과 답변이 있어요.하지만 난 이해할 수 없어...

ubuntu-9.10-desktop-amd64 + NetBeans 6.7.1이 오프에서 "있는 그대로" 설치되어 있습니다.HTTPS를 통해 사이트에 연결해야 합니다. 이를 위해 Apache의 HttpClient를 사용합니다.

튜토리얼에서 읽은 내용:

「인스톨 , 통신을 「J」로 SE를 올바르게 인스톨 하면, SSL 경유로 시큐어인 HTTP 통신이 다음과 같이 됩니다.
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 및 TrustManager 등이 없을 수 있습니다.)

https://mms.nw.ru은 기본 신뢰 관리자 세트에 없는 자체 서명된 인증서를 사용합니다.이 문제를 해결하려면 다음 중 하나를 수행합니다.

  • SSLContext a 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 키 저장소에 인증서를 추가해야 합니다.

https 프로토콜로 실행되는 SSL 지원 서버와 함께 작동하는 클라이언트에서 작업할 때 서버 인증서가 인증 기관에서 발급한 것이 아니라 개인 CMS에서 자체 서명 또는 발급한 경우 '요청된 대상에 대한 올바른 인증서 경로를 찾을 수 없음' 오류가 발생할 수 있습니다.

진정하라구.클라이언트가 Java로 작성된 경우 신뢰할 수 있는 Java 키 저장소에 서버 인증서를 추가하면 됩니다.서버가 인스톨 되어 있는 머신에 액세스 할 수 없는 경우는, 어떻게 하면 좋은지 궁금할 수 있습니다.당신을 도울 수 있는 간단한 프로그램이 있습니다.Java 프로그램을 다운로드하여 실행하세요.

% java InstallCert _web_site_hostname_

이 프로그램은 지정된 호스트에 대한 연결을 열고 SSL 핸드셰이크를 시작했습니다.발생한 오류의 예외 스택트레이스를 인쇄하고 서버에서 사용되는 증명서를 표시합니다.이제 신뢰할 수 있는 KeyStore에 증명서를 추가하는 프롬프트가 표시됩니다.

생각이 바뀌면 'q'를 입력합니다.증명서를 추가하려면 '1' 또는 기타 번호를 입력하여 다른 증명서(CA 증명서도 포함)를 추가합니다.다만, 통상은 그렇게 하고 싶지 않습니다.선택한 후에는 프로그램이 증명서 전체를 표시하고 현재 디렉토리의 'jsecacerts'라는 이름의 Java KeyStore에 추가합니다.

프로그램에서 사용하려면 신뢰 저장소로 사용하도록 JSE를 구성하거나 $JAVA_에 복사하십시오.HOME/jre/lib/security 디렉토리.모든 Java 응용 프로그램이 인증서를 JSE뿐만 아니라 신뢰할 수 있는 인증서로 인식하도록 하려면 해당 디렉토리의 cacerts 파일을 덮어쓸 수도 있습니다.

그 후, JSE는 호스트와의 핸드쉐이크를 완료할 수 있습니다.이것에 대해서는, 프로그램을 재실행하는 것으로 확인할 수 있습니다.

상세한 것에 대하여는, 릴랜드의 블로그요청 대상의 유효한 인정 패스를 찾을 수 없습니다」를 참조해 주세요.

Pascal 외에 Firefox -Details -> Pascal Tivent에서 .openssl s_client수입하다

이 작업은 증명서를 확인하는 방법이 있는 경우에만 수행해야 합니다.그렇지 않으면 처음 접속할 때 증명서가 다음 접속에서 예기치 않게 변경되면 적어도 오류가 발생합니다.

트러스트 스토어에 Import 하려면 다음 명령을 사용합니다.

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

기본 는 "Default Trust Store( 스토어는 "Default Store" 입니다.$JAVA_HOME/jre/lib/security/cacerts는 '비밀번호는 '비밀번호로 하다' 입니다.changeit자세한 내용은 JSE 레퍼런스 가이드를 참조하십시오.

글로벌하게 접속에 만 허가하는 는, 「」를 할 수 SSLContext 경우 for for:

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용으로 설정해야 합니다.SSLContext. (여기에 가 있습니다.)

4.과는 별도로)는 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();

는 효과가 없습니다.문제가 해결되지 않았습니다.

왜냐하면 HttpClient는 연결을 찾기 위해 지정된 connectionManager를 사용하고 지정된 connectionManager는 맞춤형 SSLConnectionSocketFactory를 등록하지 않았기 때문입니다.이 문제를 해결하려면 connection Manager에 The customized SSLConnectionSocketFactory를 등록해야 합니다.올바른 코드는 다음과 같습니다.

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

MySSLSocket Factory의 예는 여기에 있습니다.이 명령어는TrustManager모든 것을 신뢰하도록 수정할 수 있습니다(단, 이 점을 고려해야 합니다).

여기에 답을 붙여넣고 싶다:

Apache HttpClient 4.5.5에서

Apache 클라이언트 4.5.5에서 잘못된 SSL 인증서를 처리하는 방법

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

자기서명 테스트 증명서에 관한 또 다른 문제는 다음과 같습니다.

java.io 를 참조해 주세요.IOException: HTTPS 호스트 이름이 잘못됨: 다음과 같습니다.

이 에러는, HTTPS URL 에 액세스 하려고 할 때에 발생합니다.JRE의 키 저장소에 서버 인증서를 이미 설치했을 수 있습니다.단, 이 오류는 서버 증명서의 이름이 URL에 기재되어 있는 서버의 실제 도메인 이름과 일치하지 않음을 의미합니다.이 문제는 보통 CA가 발행하지 않은 증명서를 사용하는 경우에 발생합니다.

다음에, Https 를 쓰는 예를 나타냅니다.증명서 서버명을 무시하는 URL Connection DefaultHostnameVerifier:

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

EasySSLProtocolSocketFactory에서 문제가 발생하여 자체 ProtocolSocketFactory를 구현하게 되었습니다.

먼저 등록해야 합니다.

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

HttpClient client = new HttpClient();
...

다음으로 Protocol Socket Factory를 구현합니다.

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 입니다.

모든 체크를 중단하지 않고 런타임에 신뢰하는 호스트를 쉽게 추가할 수 있는 방법은 http://code.google.com/p/self-signed-cert-trust-manager/ 코드를 참조하십시오.

우연히도 같은 문제에 직면했는데, 갑자기 모든 수입품이 없어졌어요..m2 폴더에 있는 모든 내용을 삭제하려고 했습니다.그리고 모든 것을 다시 수입하려고 했지만, 여전히 아무 것도 되지 않았다.마지막으로 웹 사이트를 열었는데 IDE가 브라우저에서 다운로드 할 수 없다고 합니다.그리고 그것이 사용하고 있는 증명서를 보았고, 나의 증명서를 보았다.

$ keytool -v -list  PATH_TO_JAVA_KEYSTORE

키스토어 경로는 /Library/Java/JavaVirtual Machines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/security/certs였습니다.

특정 증명서가 존재하지 않았다는 것입니다.

증명서를 다시 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 

이 링크는 고객의 요건을 단계별로 설명합니다.어떤 증명서에 관심이 없는 경우 아래 링크의 프로세스를 진행할 수 있습니다.

주 안전하지 않은 작업이기 때문에 수행 중인 작업을 다시 확인해야 할 수 있습니다.

사용방법InstallCert생성하다jssecacerts줄서서 하다-Djavax.net.ssl.trustStore=/path/to/jssecacerts잘 작동했습니다.

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

}

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

아래 Java 1.7에 대해 제공된 지침에 따라 InstallCert.java 프로그램 파일을 사용하여 SSL 인증서를 만듭니다.

https://github.com/escline/InstallCert

Tomcat을 재시작해야 합니다.

DefaultTrustManager와 함께 다음을 사용하여 httpclient에서 매력처럼 작동합니다.정말 고마워!!@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();

언급URL : https://stackoverflow.com/questions/1828775/how-to-handle-invalid-ssl-certificates-with-apache-httpclient

반응형