Wie behebe ich den Fehler "java.security.cert.CertificateException: Keine alternativen Betreffnamen vorhanden" -Fehler?

108

Ich habe einen Java-Webdienst-Client, der einen Webdienst über HTTPS verwendet.

import javax.xml.ws.Service;

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

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

Wenn ich eine Verbindung zur Dienst-URL ( https://AAA.BBB.CCC.DDD:9443/ISomeService) herstelle, wird die Ausnahme angezeigt java.security.cert.CertificateException: No subject alternative names present.

Um das Problem zu beheben, habe ich zuerst openssl s_client -showcerts -connect AAA.BBB.CCC.DDD:9443 > certs.txtFolgendes ausgeführt und folgenden Inhalt in die Datei aufgenommen 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, jetzt muss ich

  1. extrahieren Sie den Teil certs.txtzwischen -----BEGIN CERTIFICATE-----und -----END CERTIFICATE-----,
  2. Ändern Sie es so, dass der Zertifikatsname gleich AAA.BBB.CCC.DDDund ist
  3. Importieren Sie dann das Ergebnis mit keytool -importcert -file fileWithModifiedCertificate(wobei fileWithModifiedCertificatedas Ergebnis der Operationen 1 und 2 ist).

Ist das richtig?

Wenn ja, wie genau kann ich das Zertifikat aus Schritt 1 mit IP-basierter adddress ( AAA.BBB.CCC.DDD) arbeiten lassen?

Update 1 (23.10.2013 15:37 MSK): In einer Antwort auf eine ähnliche Frage habe ich Folgendes gelesen:

Wenn Sie nicht die Kontrolle über diesen Server haben, verwenden Sie dessen Hostnamen (vorausgesetzt, dass mindestens ein CN mit diesem Hostnamen im vorhandenen Zertifikat übereinstimmt).

Was genau bedeutet "verwenden"?

Mentiflectax
quelle

Antworten:

152

Ich habe das Problem behoben, indem ich HTTPS-Überprüfungen mit dem hier vorgestellten Ansatz deaktiviert habe :

Ich habe folgenden Code in die ISomeServiceKlasse eingefügt:

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

Da ich das nur https://AAA.BBB.CCC.DDD:9443/ISomeServicezu Testzwecken verwende, ist es eine ausreichend gute Lösung.

Mentiflectax
quelle
Der in dem oben genannten Link erwähnte Ansatz scheint blockiert zu sein ( nakov.com/blog/2009/07/16/… ). Kann jemand den Link aktualisieren?
John
Ich habe versucht, die Validierung in diesem Prozess zu deaktivieren, aber die Browser-Validierung für SSL-Protokolle (Pudel-Sicherheitsanfälligkeit) gibt mir Folgendes: ssl_error_no_cypher_overlap. Irgendwelche Ideen?
Will824
Hallo, ich erhalte org.springframework.web.client.HttpClientErrorException: 403 Forbidden
73
Das Deaktivieren der HTTPS-Prüfung ist keine "Lösung". Sie sollten sagen, ich habe einen "Patch" gefunden.
Jus12
2
Dies führt zu Sicherheitslücken in Pre_prod und Production. 1. Machen Sie einen Host-Eintrag in der Windows-Host-Datei. 2. Oder fügen Sie IP- oder FQDN-Namen in die Felder für alternative Betreffnamen in den Zertifikaten ein
Shankar
34

Ich habe das gleiche Problem und mit diesem Code gelöst. Ich habe diesen Code vor dem ersten Aufruf meiner Webservices eingefügt.

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

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

Es ist einfach und funktioniert gut.

Hier ist die Originalquelle.

juanmhidalgo
quelle
3
Oder Sie können einfach den gesamten Hauptteil der Funktion verify () durch ersetzen return hostname.equals("localhost");, wenn Sie dies möchten. Das ifist völlig überflüssig.
Ein CVn
Dies war eine einfache und schnelle Lösung, mit der wir Tests in einer Testumgebung eines Anbieters durchführen konnten, für die kein ordnungsgemäßes Zertifikat vorhanden war. Tausend Dank!
dacDave
@ JuanM.Hidalgo, der für mich funktioniert hat, hat den obigen Code direkt vor dem Anruf bei platziert HttpsURLConnection connection = (HttpsURLConnection) obj.openConnection();. Ignoriert dies auch jedes Zertifikat? Da habe ich gesehen, dass eine solche Problemumgehung anfällig für Sicherheit ist. Danke dir!
ThunderWiring
Diese Antwort löste meine SSL-Zertifizierungsausnahme und das Problem mit Nicht-LDH-Zeichen. Ich konnte sehen, dass im offenen JDK ein Fehler gemeldet wurde: bugs.openjdk.java.net/browse/JDK-8170265
Akhil S Kamath
28

Dies ist eine alte Frage, aber ich hatte das gleiche Problem beim Wechsel von JDK 1.8.0_144 zu JDK 1.8.0_191

Wir haben im Changelog einen Hinweis gefunden:

Änderungsprotokoll

Wir haben die folgende zusätzliche Systemeigenschaft hinzugefügt, die in unserem Fall zur Lösung dieses Problems beigetragen hat:

-Dcom.sun.jndi.ldap.object.disableEndpointIdentification=true
Markus
quelle
25

Die Überprüfung der Zertifikatidentität erfolgt anhand der Anforderungen des Clients.

Wenn Ihr Client verwendet https://xxx.xxx.xxx.xxx/something(wo xxx.xxx.xxx.xxxist eine IP-Adresse), wird die Zertifikatidentität mit dieser IP-Adresse verglichen (theoretisch nur mit einer IP-SAN-Erweiterung).

Wenn Ihr Zertifikat kein IP-SAN, sondern DNS-SANs hat (oder wenn kein DNS-SAN, ein allgemeiner Name im Betreff-DN), können Sie dies zum Laufen bringen, indem Sie Ihren Client dazu bringen, stattdessen eine URL mit diesem Hostnamen (oder einen Hostnamen) zu verwenden für die das Zertifikat gültig wäre, wenn es mehrere mögliche Werte gibt). Wenn Ihr Zertifikat beispielsweise einen Namen für hat www.example.com, verwenden Sie https://www.example.com/something.

Natürlich benötigen Sie diesen Hostnamen, um in diese IP-Adresse aufgelöst zu werden.

Wenn außerdem DNS-SANs vorhanden sind, wird der CN im Betreff-DN ignoriert. Verwenden Sie daher in diesem Fall einen Namen, der mit einem der DNS-SANs übereinstimmt.

Bruno
quelle
1
Ich kann nicht über auf den Dienst zugreifen http://www.example.com/someservice. Ist es richtig, dass https://AAA.BBB.CCC.DDD:9443/ISomeServiceich , damit das Zertifikat mit der IP-basierten Adresse ( ) funktioniert , alle CNFelder auf AAA.BBB.CCC.DDD( in der obigen Datei someSubdomain.someorganisation.comdurch ersetzen AAA.BBB.CCC.DDD) setzen und die resultierende Zertifikatdatei importieren muss?
Mentiflectax
Sie können nichts gegen den CN oder das Zertifikat unternehmen, wenn Sie nicht die Kontrolle über den Server haben.
Bruno
/etc/hosts
Um zu
1
In meinem Code habe ich die Anfrage an eine öffentliche IP gesendet, aber das Zertifikat CN war ein Hostname. In meinem Code habe ich die IP durch den Hostnamen ersetzt und meine / etc / hosts so konfiguriert, dass dieser Hostname der IP zugeordnet wird. Gelöst!
Leopold Gault
15

So importieren Sie das Zertifikat:

  1. Extrahieren Sie das Zertifikat vom Server, z. B. openssl s_client -showcerts -connect AAA.BBB.CCC.DDD:9443 > certs.txtwerden Zertifikate im PEM-Format extrahiert.
  2. Konvertieren Sie das Zertifikat in das DER-Format, da dies von keytool erwartet wird, z openssl x509 -in certs.txt -out certs.der -outform DER
  3. Jetzt möchten Sie dieses Zertifikat in die Systemstandarddatei 'cacert' importieren. Suchen Sie die Systemstandarddatei 'cacerts' für Ihre Java-Installation. Schauen Sie sich an, wie Sie den Speicherort der Cacerts der Standard-Java-Installation ermitteln.
  4. Importieren Sie die Zertifikate in diese Cacerts-Datei: Das sudo keytool -importcert -file certs.der -keystore <path-to-cacerts>Standardkennwort für Cacerts lautet 'changeit'.

Wenn das Zertifikat für einen vollqualifizierten Domänennamen ausgestellt wurde und Sie versuchen, eine Verbindung über die IP-Adresse in Ihrem Java-Code herzustellen, sollte dies wahrscheinlich in Ihrem Code behoben sein, anstatt mit dem Zertifikat selbst herumzuspielen. Ändern Sie Ihren Code, um eine Verbindung per FQDN herzustellen. Wenn der vollqualifizierte Domänenname auf Ihrem Entwicklungscomputer nicht auflösbar ist, fügen Sie ihn einfach Ihrer Hosts-Datei hinzu oder konfigurieren Sie Ihren Computer mit einem DNS-Server, der diesen vollqualifizierten Domänennamen auflösen kann.

andreycpp
quelle
"Wenn FQDN auf Ihrem Entwicklungscomputer nicht auflösbar ist, fügen Sie es einfach Ihrer Hosts-Datei hinzu" - half. Vielen Dank!
Woland
Ich habe das Gleiche getan, aber das Problem bleibt bestehen. Gibt es noch etwas, das mit diesem Ansatz getan werden kann?
pkgajulapalli
9

Ich habe dieses Problem auf die richtige Weise behoben, indem ich die Betreff-Alt-Namen in das Zertifikat eingefügt habe, anstatt Änderungen am Code vorzunehmen oder SSL zu deaktivieren, anders als in anderen Antworten hier vorgeschlagen. Wenn Sie deutlich sehen, dass in der Ausnahme "Betreff-Alt-Namen fehlen" angezeigt wird, sollten Sie sie am besten hinzufügen

Bitte schauen Sie auf diesen Link, um Schritt für Schritt zu verstehen .

Der obige Fehler bedeutet, dass in Ihrer JKS-Datei die erforderliche Domäne fehlt, für die Sie versuchen, auf die Anwendung zuzugreifen. Sie müssen Open SSL und das Schlüsseltool verwenden, um mehrere Domänen hinzuzufügen

  1. Kopieren Sie die Datei openssl.cnf in ein aktuelles Verzeichnis
  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. Exportieren Sie die öffentliche Schlüsseldatei (.pem) in das PKS12-Format. Dadurch werden Sie zur Eingabe des Kennworts aufgefordert

    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. Erstellen Sie a.JKS aus selbstsigniertem PEM (Keystore).

    keytool -importkeystore -destkeystore keystore.jks -deststoretype PKCS12 -srcstoretype PKCS12 -srckeystore keystore.p12
  7. Generieren Sie ein Zertifikat aus der obigen Keystore- oder JKS-Datei

    keytool -export -keystore keystore.jks -alias myalias -file selfsigned.crt
  8. Da das oben genannte Zertifikat selbstsigniert ist und nicht von der Zertifizierungsstelle validiert wurde, muss es im Truststore hinzugefügt werden (Cacerts-Datei am folgenden Speicherort für MAC, für Windows, finden Sie heraus, wo Ihr JDK installiert ist.)

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

Ursprüngliche Antwort auf diesen Link hier gepostet .

Abhishek Galoda
quelle
4

Möglicherweise möchten Sie nicht alle SSL-Überprüfungen deaktivieren. Daher können Sie die Überprüfung des Hostnamens einfach deaktivieren, was etwas weniger beängstigend ist als die Alternative:

HttpsURLConnection.setDefaultHostnameVerifier(
    SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

[BEARBEITEN]

Wie von conapart3 erwähnt, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIERist es jetzt veraltet, sodass es möglicherweise in einer späteren Version entfernt wird, sodass Sie möglicherweise in Zukunft gezwungen sind, Ihre eigenen zu rollen, obwohl ich immer noch sagen würde, dass ich mich von Lösungen fernhalten würde, bei denen alle Überprüfungen deaktiviert sind.

lebenswichtig
quelle
2
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIERist jetzt veraltet.
conapart3
3

Mein Problem mit diesem Fehler wurde behoben, indem die vollständige URL "qatest.ourCompany.com/webService" anstelle von "qatest / webService" verwendet wurde. Grund war, dass unser Sicherheitszertifikat einen Platzhalter hatte, dh "* .ourCompany.com". Nachdem ich die vollständige Adresse eingegeben hatte, verschwand die Ausnahme. Hoffe das hilft.

Shahriar
quelle
2

Habe es bereits unter https://stackoverflow.com/a/53491151/1909708 beantwortet .

Dies schlägt fehl, da weder der allgemeine Name des Zertifikats ( CNin der Zertifizierung Subject) noch einer der alternativen Namen ( Subject Alternative Nameim Zertifikat) mit dem Zielhostnamen oder der IP-Adresse übereinstimmen.

Wenn beispielsweise von einer JVM aus versucht wird, eine Verbindung zu einer IP-Adresse ( WW.XX.YY.ZZ) und nicht zum DNS-Namen ( https://stackoverflow.com ) herzustellen, schlägt die HTTPS-Verbindung fehl, da das im Java Truststore gespeicherte Zertifikat einen cacertsgemeinsamen Namen erwartet (oder alternativer Name des Zertifikats wie stackexchange.com oder * .stackoverflow.com usw.), um der Zieladresse zu entsprechen.

Bitte überprüfen Sie: 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();

Oben wurde ein implementiertes HostnameVerifierObjekt übergeben, das immer zurückgegeben wird true:

new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession sslSession) {
            return true;
        }
    }
Himadri Pant
quelle
1

Für Spring Boot RestTemplate:

  • org.apache.httpcomponents.httpcoreAbhängigkeit hinzufügen
  • Verwendung NoopHostnameVerifierfür SSL Factory:

    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);
Grigory Kislin
quelle
0

Ich kam zu dieser Frage, nachdem ich dieselbe Fehlermeldung erhalten hatte. In meinem Fall hatten wir jedoch zwei URLs mit unterschiedlichen Subdomains ( http://example1.xxx.com/someservice und http://example2.yyy.com/someservice ), die an denselben Server geleitet wurden. Dieser Server hatte nur ein Platzhalterzertifikat für die Domäne * .xxx.com. Bei Verwendung des Dienstes über die zweite Domäne stimmt das gefundene Zertifikat (* .xxx.com) nicht mit der angeforderten Domäne (* .yyy.com) überein, und der Fehler tritt auf.

In diesem Fall sollten wir nicht versuchen, eine solche Fehlermeldung durch Verringern der SSL-Sicherheit zu beheben, sondern den Server und die Zertifikate darauf überprüfen.

Gert
quelle
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
quelle
1
Bitte fügen Sie Ihrem Code einen erläuternden Text hinzu. Siehe stackoverflow.com/help/how-to-answer
jasie
1
Dies ist eine Sicherheitslücke. Auf diese Weise wird die Zertifikatsüberprüfung zunächst deaktiviert. Jeder, der diese Lösung kopiert und einfügt, erstellt einen Sicherheitsfehler in seiner Software.
Marek Puchalski
0

Ich habe im Springboot 2-Wege-SSL durchlaufen. Ich habe alle korrekten Konfigurationsservice Tomcat Server und Service Caller RestTemplate gemacht. Es wurde jedoch die Fehlermeldung "java.security.cert.CertificateException: Keine alternativen Betreffnamen vorhanden" angezeigt.

Nachdem ich die Lösungen durchgesehen hatte, stellte ich fest, dass JVM dieses Zertifikat benötigt, da sonst ein Handshake-Fehler auftritt.

Nun, wie man dies zu JVM hinzufügt.

Gehen Sie zur Datei jre / lib / security / cacerts. Wir müssen unsere Serverzertifikatsdatei zu dieser Cacerts-Datei von jvm hinzufügen.

Befehl zum Hinzufügen eines Serverzertifikats zur Cacerts-Datei über die Befehlszeile in Windows.

C: \ Programme \ 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

Überprüfen Sie, ob das Serverzertifikat installiert ist oder nicht:

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

Sie können die Liste der installierten Zertifikate sehen:

Für weitere Informationen: https://sachin4java.blogspot.com/2019/08/javasecuritycertcertificateexception-no.html

Sachin Rane
quelle
0

Fügen Sie den Hosteintrag mit der IP hinzu, die dem CN im Zertifikat entspricht

CN = someSubdomain.someorganisation.com

Aktualisieren Sie jetzt die IP mit dem CN-Namen, unter dem Sie versuchen, auf die URL zuzugreifen.

Es hat bei mir funktioniert.

Manoj
quelle
0

Dieser Code funktioniert wie ein Zauber und verwendet das restTemple-Objekt für den Rest des Codes.

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

Wenn Sie über ein Zertifikat mit CN- und Betreff-Alternativnamen (SAN) verfügen und Ihre Anfrage auf der Grundlage des CN-Inhalts stellen, muss dieser bestimmte Inhalt auch unter SAN vorhanden sein, da er sonst mit dem betreffenden Fehler fehlschlägt.

In meinem Fall hatte CN etwas, SAN hatte etwas anderes. Ich musste die SAN-URL verwenden, und dann funktionierte es einwandfrei.

Tudor
quelle
-3

Fügen Sie Ihre IP-Adresse in die Hosts-Datei ein, die sich im Ordner C: \ Windows \ System32 \ drivers \ etc. Befindet. Fügen Sie auch IP und Domain Name der IP-Adresse hinzu. Beispiel: aaa.bbb.ccc.ddd [email protected]

Prakash Soni
quelle
-5

Ich habe das Problem folgendermaßen gelöst.

1. Eine Klasse erstellen. Die Klasse hat einige leere Implementierungen

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. Erstellen einer Methode

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. Rufen Sie die disableSSL () -Methode auf, bei der die Ausnahme ausgelöst wird. Es hat gut funktioniert.
Aditya Bhuyan
quelle