Jak naprawić błąd „java.security.cert.CertificateException: brak alternatywnych nazw podmiotów”?

108

Mam klienta usługi sieciowej Java, który korzysta z usługi sieciowej za pośrednictwem protokołu HTTPS.

import javax.xml.ws.Service;

@WebServiceClient(name = "ISomeService", targetNamespace = "http://tempuri.org/", wsdlLocation = "...")
public class ISomeService
    extends Service
{

    public ISomeService() {
        super(__getWsdlLocation(), ISOMESERVICE_QNAME);
    }

Kiedy łączę się z adresem URL usługi ( https://AAA.BBB.CCC.DDD:9443/ISomeService), pojawia się wyjątek java.security.cert.CertificateException: No subject alternative names present.

Aby to naprawić, najpierw uruchomiłem openssl s_client -showcerts -connect AAA.BBB.CCC.DDD:9443 > certs.txti otrzymałem następującą zawartość w pliku certs.txt:

CONNECTED(00000003)
---
Certificate chain
 0 s:/CN=someSubdomain.someorganisation.com
   i:/CN=someSubdomain.someorganisation.com
-----BEGIN CERTIFICATE-----
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-----END CERTIFICATE-----
---
Server certificate
subject=/CN=someSubdomain.someorganisation.com
issuer=/CN=someSubdomain.someorganisation.com
---
No client certificate CA names sent
---
SSL handshake has read 489 bytes and written 236 bytes
---
New, TLSv1/SSLv3, Cipher is RC4-MD5
Server public key is 512 bit
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : RC4-MD5            
    Session-ID: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    Session-ID-ctx:                 
    Master-Key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    Key-Arg   : None
    Start Time: 1382521838
    Timeout   : 300 (sec)
    Verify return code: 21 (unable to verify the first certificate)
---

AFAIK, teraz muszę

  1. wyodrębnij część certs.txtmiędzy -----BEGIN CERTIFICATE-----a -----END CERTIFICATE-----,
  2. zmodyfikuj go tak, aby nazwa certyfikatu była równa AAA.BBB.CCC.DDDi
  3. następnie zaimportuj wynik za pomocą keytool -importcert -file fileWithModifiedCertificate(gdzie fileWithModifiedCertificatejest wynikiem operacji 1 i 2).

Czy to jest poprawne?

Jeśli tak, jak dokładnie mogę sprawić, by certyfikat z kroku 1 działał z adresem IP opartym na adresie IP ( AAA.BBB.CCC.DDD)?

Aktualizacja 1 (23.10.2013 15:37 MSK): W odpowiedzi na podobne pytanie przeczytałem:

Jeśli nie masz kontroli nad tym serwerem, użyj jego nazwy hosta (pod warunkiem, że istnieje co najmniej CN pasująca do tej nazwy hosta w istniejącym certyfikacie).

Co dokładnie oznacza „używać”?

Mentiflectax
źródło

Odpowiedzi:

153

Naprawiłem problem, wyłączając sprawdzanie HTTPS przy użyciu podejścia przedstawionego tutaj :

W ISomeServiceklasie umieściłem następujący kod :

static {
    disableSslVerification();
}

private static void disableSslVerification() {
    try
    {
        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
            public void checkClientTrusted(X509Certificate[] certs, String authType) {
            }
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
            }
        }
        };

        // Install the all-trusting trust manager
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

        // Create all-trusting host name verifier
        HostnameVerifier allHostsValid = new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };

        // Install the all-trusting host verifier
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (KeyManagementException e) {
        e.printStackTrace();
    }
}

Ponieważ używam go tylko https://AAA.BBB.CCC.DDD:9443/ISomeServicedo celów testowych, jest to wystarczająco dobre rozwiązanie.

Mentiflectax
źródło
Podejście wymienione w powyższym linku wydaje się być zablokowane ( nakov.com/blog/2009/07/16/ ... ). Czy ktoś może zaktualizować link?
Jan
Próbowałem wyłączyć walidację wykonując ten proces, ale sprawdzanie poprawności przeglądarki pod kątem protokołów SSL (luka w Poodle) daje mi: ssl_error_no_cypher_overlap. Jakieś pomysły?
will824
Witam, otrzymuję org.springframework.web.client.HttpClientErrorException: 403 Forbidden
73
wyłączenie sprawdzania HTTPS nie jest „rozwiązaniem”. Powinieneś powiedzieć, że znalazłem „łatkę”.
Jus12
2
Spowoduje to lukę w zabezpieczeniach Pre_prod i Production. 1. Wprowadź nazwę hosta w pliku hosta systemu Windows 2. Lub dodaj nazwy IP lub FQDN w polach alternatywnych nazw podmiotu w certyfikatach
Shankar,
34

Mam ten sam problem i rozwiązałem go za pomocą tego kodu. Ten kod umieściłem przed pierwszym wywołaniem moich usług sieciowych.

javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
new javax.net.ssl.HostnameVerifier(){

    public boolean verify(String hostname,
            javax.net.ssl.SSLSession sslSession) {
        return hostname.equals("localhost");
    }
});

To proste i działa dobrze.

Oto oryginalne źródło.

juanmhidalgo
źródło
3
Lub możesz po prostu zamienić całą treść funkcji verify () na return hostname.equals("localhost");, jeśli chcesz to zrobić. Jest ifto całkowicie zbędne.
CVn
To była prosta i szybka poprawka, która pomogła nam przetestować w środowisku testowym dostawcy, które nie miało odpowiedniego certyfikatu. Stukrotne dzięki!
dacDave
@ JuanM.Hidalgo, który działał dla mnie, umieścił powyższy kod tuż przed wezwaniem do HttpsURLConnection connection = (HttpsURLConnection) obj.openConnection();. Czy to ignoruje każdy certyfikat? Odkąd widziałem, że takie obejście jest podatne na zagrożenia. Dziękuję Ci!
ThunderWiring
ta odpowiedź rozwiązała mój wyjątek certyfikatu SSL i problem ze znakami spoza LDH, widziałem, że jest błąd zgłoszony w otwartym JDK, bugs.openjdk.java.net/browse/JDK-8170265
Akhil S Kamath
28

To jest stare pytanie, ale miałem ten sam problem podczas przechodzenia z JDK 1.8.0_144 na jdk 1.8.0_191

Znaleźliśmy wskazówkę w dzienniku zmian:

Changelog

dodaliśmy następującą dodatkową właściwość systemową, która pomogła w naszym przypadku rozwiązać ten problem:

-Dcom.sun.jndi.ldap.object.disableEndpointIdentification=true
Markus
źródło
25

Weryfikacja tożsamości certyfikatu jest przeprowadzana na podstawie żądań klienta.

Gdy klient używa https://xxx.xxx.xxx.xxx/something(gdzie xxx.xxx.xxx.xxxjest adres IP), tożsamość certyfikatu jest sprawdzana w odniesieniu do tego adresu IP (teoretycznie tylko przy użyciu rozszerzenia IP SAN).

Jeśli Twój certyfikat nie ma IP SAN, ale DNS SAN (lub jeśli nie ma DNS SAN, nazwy pospolitej w nazwie wyróżniającej podmiotu), możesz sprawić, że zadziała, używając zamiast tego adresu URL z tą nazwą hosta (lub nazwą hosta dla których certyfikat byłby ważny, jeśli istnieje wiele możliwych wartości). Na przykład, jeśli certyfikat ma nazwę dla www.example.com, użyj https://www.example.com/something.

Oczywiście będziesz potrzebować tej nazwy hosta, aby rozwiązać ten adres IP.

Ponadto, jeśli istnieją jakiekolwiek sieci DNS SAN, CN w nazwie wyróżniającej podmiotu zostanie zignorowana, dlatego w tym przypadku należy użyć nazwy pasującej do jednej z sieci DNS SAN.

Bruno
źródło
1
Nie mogę uzyskać dostępu do usługi przez http://www.example.com/someservice. Czy jest to prawidłowe, że w celu zaświadczenia do pracy z adresu IP (z siedzibą https://AAA.BBB.CCC.DDD:9443/ISomeService), muszę ustawić wszystkie CNpola do AAA.BBB.CCC.DDD(zastąpienie someSubdomain.someorganisation.comprzez AAA.BBB.CCC.DDDw pliku powyżej) i zaimportować wynikowy plik certyfikatu?
Mentiflectax
Nie możesz nic zrobić z CN lub certyfikatem, jeśli nie masz kontroli nad serwerem.
Bruno,
aby uzyskać dostęp do adresu IP w celach testowych, możesz tymczasowo zmodyfikować swój /etc/hostsplik lub jego odpowiednik
tyoc213
1
W swoim kodzie wysyłałem żądanie na publiczny adres IP, ale certyfikat CN był nazwą hosta. Dlatego w moim kodzie zastąpiłem adres IP nazwą hosta i skonfigurowałem plik / etc / hosts, aby skojarzył tę nazwę hosta z adresem IP. Rozwiązany !
Leopold Gault
15

Aby zaimportować certyfikat:

  1. Wyodrębnij certyfikat z serwera, np. openssl s_client -showcerts -connect AAA.BBB.CCC.DDD:9443 > certs.txtSpowoduje to wyodrębnienie certyfikatów w formacie PEM.
  2. Przekonwertuj certyfikat na format DER, ponieważ tego oczekuje keytool, np openssl x509 -in certs.txt -out certs.der -outform DER
  3. Teraz chcesz zaimportować ten certyfikat do domyślnego pliku „cacert” systemu. Znajdź domyślny systemowy plik „cacerts” do instalacji oprogramowania Java. Zapoznaj się z artykułem Jak uzyskać lokalizację plików cookie domyślnej instalacji Java?
  4. Zaimportuj certyfikaty do tego pliku cacerts: sudo keytool -importcert -file certs.der -keystore <path-to-cacerts>Domyślne hasło cacerts to „changeit”.

Jeśli certyfikat został wystawiony dla nazwy FQDN i próbujesz połączyć się za pomocą adresu IP w kodzie Java, prawdopodobnie powinno to zostać naprawione w kodzie, a nie z samym certyfikatem. Zmień kod, aby łączyć się przez FQDN. Jeśli nazwa FQDN nie jest rozpoznawalna na twoim komputerze deweloperskim, po prostu dodaj ją do pliku hosts lub skonfiguruj swój komputer z serwerem DNS, który może rozpoznać tę nazwę FQDN.

andreycpp
źródło
„Jeśli nazwa FQDN nie jest rozpoznawalna na twojej maszynie deweloperskiej, po prostu dodaj ją do pliku hosts” - pomogło. Wielkie dzięki!
Woland
Zrobiłem to samo, ale problem nadal występuje. Czy jest coś jeszcze, co można zrobić, stosując to podejście?
pkgajulapalli
9

Naprawiłem ten problem we właściwy sposób, dodając nazwy alternatywne tematu w certyfikacie, zamiast wprowadzać jakiekolwiek zmiany w kodzie lub wyłączając SSL, w przeciwieństwie do tego, co sugerują inne odpowiedzi. Jeśli widzisz wyraźnie, wyjątek mówi, że „Brakuje nazw alternatywnych tematu”, więc należy je dodać

Proszę spojrzeć na ten link, aby zrozumieć krok po kroku .

Powyższy błąd oznacza, że ​​w pliku JKS brakuje wymaganej domeny, na której próbujesz uzyskać dostęp do aplikacji. Aby dodać wiele domen, musisz użyć protokołu Open SSL i narzędzia klucza

  1. Skopiuj openssl.cnf do bieżącego katalogu
  2. echo '[ subject_alt_name ]' >> openssl.cnf
  3. echo 'subjectAltName = DNS:example.mydomain1.com, DNS:example.mydomain2.com, DNS:example.mydomain3.com, DNS: localhost'>> openssl.cnf
  4. openssl req -x509 -nodes -newkey rsa:2048 -config openssl.cnf -extensions subject_alt_name -keyout private.key -out self-signed.pem -subj '/C=gb/ST=edinburgh/L=edinburgh/O=mygroup/OU=servicing/CN=www.example.com/[email protected]' -days 365
  5. Wyeksportuj plik klucza publicznego (.pem) do formatu PKS12. Spowoduje to wyświetlenie monitu o hasło

    openssl pkcs12 -export -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -export -in
    self-signed.pem -inkey private.key -name myalias -out keystore.p12
  6. Utwórz plik JKS z samodzielnie podpisanego PEM (Keystore)

    keytool -importkeystore -destkeystore keystore.jks -deststoretype PKCS12 -srcstoretype PKCS12 -srckeystore keystore.p12
  7. Wygeneruj certyfikat z pliku Keystore lub JKS

    keytool -export -keystore keystore.jks -alias myalias -file selfsigned.crt
  8. Ponieważ powyższy certyfikat jest samopodpisany i nie jest sprawdzany przez CA, należy go dodać do Truststore (plik Cacerts w poniższej lokalizacji dla MAC, dla Windows, dowiedz się, gdzie jest zainstalowany pakiet JDK).

    sudo keytool -importcert -file selfsigned.crt -alias myalias -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/security/cacerts

Oryginalna odpowiedź zamieszczona pod tym linkiem tutaj .

Abhishek Galoda
źródło
4

Możesz nie chcieć wyłączać całej weryfikacji SSL, więc możesz po prostu wyłączyć weryfikację nazwy hosta za pomocą tego, co jest nieco mniej przerażające niż alternatywa:

HttpsURLConnection.setDefaultHostnameVerifier(
    SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

[EDYTOWAĆ]

Jak wspomniano w conapart3, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIERjest teraz przestarzały, więc może zostać usunięty w późniejszej wersji, więc w przyszłości możesz być zmuszony do zainstalowania własnego, chociaż nadal powiedziałbym, że unikałbym rozwiązań, w których cała weryfikacja jest wyłączona.

niezwykłe życie
źródło
2
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIERjest teraz przestarzała.
conapart3
3

mój problem z wyświetlaniem tego błędu został rozwiązany przy użyciu pełnego adresu URL „qatest.ourCompany.com/webService” zamiast tylko „qatest / webService”. Powodem było to, że nasz certyfikat bezpieczeństwa zawierał symbol wieloznaczny, tj. „* .OurCompany.com”. Kiedy podałem pełny adres, wyjątek zniknął. Mam nadzieję że to pomoże.

Shahriar
źródło
2

Odpowiedziałem już na https://stackoverflow.com/a/53491151/1909708 .

Nie udaje się to, ponieważ ani nazwa pospolita certyfikatu ( CNw certyfikacji Subject), ani żadna z nazw alternatywnych ( Subject Alternative Namew certyfikacie) nie są zgodne z docelową nazwą hosta lub adresem IP.

Na przykład z maszyny JVM, podczas próby połączenia się z adresem IP ( WW.XX.YY.ZZ), a nie nazwą DNS ( https://stackoverflow.com ), połączenie HTTPS nie powiedzie się, ponieważ certyfikat przechowywany w magazynie zaufanych certyfikatów java cacertsoczekuje nazwy pospolitej (lub alternatywna nazwa certyfikatu, taka jak stackexchange.com lub * .stackoverflow.com itp.), aby dopasować adres docelowy.

Sprawdź: https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#HostnameVerifier

    HttpsURLConnection urlConnection = (HttpsURLConnection) new URL("https://WW.XX.YY.ZZ/api/verify").openConnection();
    urlConnection.setSSLSocketFactory(socketFactory());
    urlConnection.setDoOutput(true);
    urlConnection.setRequestMethod("GET");
    urlConnection.setUseCaches(false);
    urlConnection.setHostnameVerifier(new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession sslSession) {
            return true;
        }
    });
    urlConnection.getOutputStream();

Powyżej przekazano zaimplementowany HostnameVerifierobiekt, który zawsze zwraca true:

new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession sslSession) {
            return true;
        }
    }
Himadri Pant
źródło
1

Do butów wiosennych RestTemplate:

  • dodaj org.apache.httpcomponents.httpcorezależność
  • Użyj NoopHostnameVerifierdla fabryki SSL:

    SSLContext sslContext = new SSLContextBuilder()
            .loadTrustMaterial(new URL("file:pathToServerKeyStore"), storePassword)
    //        .loadKeyMaterial(new URL("file:pathToClientKeyStore"), storePassword, storePassword)
            .build();
    SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
    CloseableHttpClient client = HttpClients.custom().setSSLSocketFactory(socketFactory).build();
    HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(client);
    RestTemplate restTemplate = new RestTemplate(factory);
Grigorij Kislin
źródło
0

Otrzymałem to pytanie po tym, jak otrzymałem ten sam komunikat o błędzie. Jednak w moim przypadku mieliśmy dwa adresy URL z różnymi subdomenami ( http://example1.xxx.com/someservice i http://example2.yyy.com/someservice ), które były kierowane na ten sam serwer. Ten serwer miał tylko jeden certyfikat wieloznaczny dla domeny * .xxx.com. Podczas korzystania z usługi za pośrednictwem drugiej domeny znaleziony certyfikat (* .xxx.com) nie pasuje do żądanej domeny (* .yyy.com) i pojawia się błąd.

W takim przypadku nie powinniśmy próbować naprawiać takiej wiadomości o błędzie poprzez obniżenie bezpieczeństwa SSL, ale powinniśmy sprawdzić serwer i certyfikaty na nim.

Gert
źródło
0
public class RESTfulClientSSL {

    static TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            // TODO Auto-generated method stub
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            // TODO Auto-generated method stub
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            // TODO Auto-generated method stub
            return null;
        }
    }};

    public class NullHostNameVerifier implements HostnameVerifier {
        /*
         * (non-Javadoc)
         *
         * @see javax.net.ssl.HostnameVerifier#verify(java.lang.String,
         * javax.net.ssl.SSLSession)
         */
        @Override
        public boolean verify(String arg0, SSLSession arg1) {
            // TODO Auto-generated method stub
            return true;
        }
    }

    public static void main(String[] args) {

        HttpURLConnection connection = null;
        try {

            HttpsURLConnection.setDefaultHostnameVerifier(new RESTfulwalkthroughCer().new NullHostNameVerifier());
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());


            String uriString = "https://172.20.20.12:9443/rest/hr/exposed/service";
            URL url = new URL(uriString);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            //connection.setRequestMethod("POST");

            BASE64Encoder encoder = new BASE64Encoder();
            String username = "admin";
            String password = "admin";
            String encodedCredential = encoder.encode((username + ":" + password).getBytes());
            connection.setRequestProperty("Authorization", "Basic " + encodedCredential);

            connection.connect();
            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                StringBuffer stringBuffer = new StringBuffer();
                String line = "";
                while ((line = reader.readLine()) != null) {
                    stringBuffer.append(line);
                }
                String content = stringBuffer.toString();
                System.out.println(content);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }
}
user11888077
źródło
1
proszę dodać tekst wyjaśniający do swojego kodu. Zobacz stackoverflow.com/help/how-to-answer
jasie
1
To jest luka w zabezpieczeniach. W ten sposób w pierwszej kolejności wyłącza się weryfikację certyfikatu. Każdy, kto kopiuje i wkleja to rozwiązanie, stworzy błąd bezpieczeństwa w swoim oprogramowaniu.
Marek Puchalski
0

Przechodziłem przez 2-drożny SSL w springboot. Zrobiłem całą poprawną konfigurację serwera tomcat usługi i wywołującego usługę RestTemplate. ale otrzymywałem błąd: „java.security.cert.CertificateException: brak alternatywnych nazw tematów”

Po przejściu przez rozwiązania stwierdziłem, że JVM potrzebuje tego certyfikatu, w przeciwnym razie wyświetla błąd uzgadniania.

Teraz, jak dodać to do JVM.

przejdź do pliku jre / lib / security / cacerts. musimy dodać nasz plik certyfikatu serwera do tego pliku cacerts jvm.

Polecenie dodania certyfikatu serwera do pliku cacerts za pomocą wiersza poleceń w systemie Windows.

C: \ Program Files \ Java \ jdk1.8.0_191 \ jre \ lib \ security> keytool -import -noprompt -trustcacerts -alias sslserver -file E: \ spring_cloud_sachin \ ssl_keys \ sslserver.cer -keystore cacerts -storepass changeit

Sprawdź, czy certyfikat serwera jest zainstalowany, czy nie:

C: \ Program Files \ Java \ jdk1.8.0_191 \ jre \ lib \ security> keytool -list -keystore cacerts

możesz zobaczyć listę zainstalowanych certyfikatów:

więcej szczegółów: https://sachin4java.blogspot.com/2019/08/javasecuritycertcertificateexception-no.html

Sachin Rane
źródło
0

dodaj wpis hosta z adresem IP odpowiadającym CN w certyfikacie

CN = someSubdomain.someorganisation.com

teraz zaktualizuj adres IP nazwą CN, do której próbujesz uzyskać dostęp do adresu URL.

U mnie to zadziałało.

manoj
źródło
0

Ten kod będzie działał jak urok i użyje obiektu restTemple do pozostałej części kodu.

  RestTemplate restTemplate = new RestTemplate();   
  TrustStrategy acceptingTrustStrategy = new TrustStrategy() {
            @Override
            public boolean isTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) {
                return true;
            }

        };

        SSLContext sslContext = null;
        try {
            sslContext = org.apache.http.ssl.SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy)
                    .build();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
        SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier());
        CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(csf).build();
        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
        requestFactory.setHttpClient(httpClient);

        restTemplate.setRequestFactory(requestFactory);
}
Nizam Mahammad
źródło
0

Jeśli masz certyfikat z zarówno CN, jak i alternatywnymi nazwami podmiotu (SAN), jeśli składasz żądanie w oparciu o zawartość CN, ta konkretna treść musi również znajdować się w sieci SAN, w przeciwnym razie błąd zakończy się niepowodzeniem.

W moim przypadku CN coś miało, SAN coś innego. Musiałem użyć adresu URL SAN, a potem działało dobrze.

Tudor
źródło
-3

Dodaj swój adres IP do pliku hosts, który znajduje się w folderze C: \ Windows \ System32 \ drivers \ etc. Dodaj również adres IP i nazwę domeny adresu IP. przykład: aaa.bbb.ccc.ddd [email protected]

Prakash Soni
źródło
-5

Problem rozwiązałem w następujący sposób.

1. Tworzenie klasy. Klasa ma kilka pustych implementacji

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

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

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

@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString)
        throws CertificateException {
    // TODO Auto-generated method stub

}

@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString)
        throws CertificateException {
    // TODO Auto-generated method stub

}

2. Tworzenie metody

private static void disableSSL() {
    try {
        TrustManager[] trustAllCerts = new TrustManager[] { new MyTrustManager() };

        // Install the all-trusting trust manager
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HostnameVerifier allHostsValid = new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

  1. Wywołaj metodę disableSSL (), w której jest zgłaszany wyjątek. Działało dobrze.
Aditya Bhuyan
źródło