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.txt
Folgendes 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
- extrahieren Sie den Teil
certs.txt
zwischen-----BEGIN CERTIFICATE-----
und-----END CERTIFICATE-----
, - Ändern Sie es so, dass der Zertifikatsname gleich
AAA.BBB.CCC.DDD
und ist - Importieren Sie dann das Ergebnis mit
keytool -importcert -file fileWithModifiedCertificate
(wobeifileWithModifiedCertificate
das 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"?
quelle
Ich habe das gleiche Problem und mit diesem Code gelöst. Ich habe diesen Code vor dem ersten Aufruf meiner Webservices eingefügt.
Es ist einfach und funktioniert gut.
Hier ist die Originalquelle.
quelle
return hostname.equals("localhost");
, wenn Sie dies möchten. Dasif
ist völlig überflüssig.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!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:
quelle
Die Überprüfung der Zertifikatidentität erfolgt anhand der Anforderungen des Clients.
Wenn Ihr Client verwendet
https://xxx.xxx.xxx.xxx/something
(woxxx.xxx.xxx.xxx
ist 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 Siehttps://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.
quelle
http://www.example.com/someservice
. Ist es richtig, dasshttps://AAA.BBB.CCC.DDD:9443/ISomeService
ich , damit das Zertifikat mit der IP-basierten Adresse ( ) funktioniert , alleCN
Felder aufAAA.BBB.CCC.DDD
( in der obigen DateisomeSubdomain.someorganisation.com
durch ersetzenAAA.BBB.CCC.DDD
) setzen und die resultierende Zertifikatdatei importieren muss?/etc/hosts
So importieren Sie das Zertifikat:
openssl s_client -showcerts -connect AAA.BBB.CCC.DDD:9443 > certs.txt
werden Zertifikate im PEM-Format extrahiert.openssl x509 -in certs.txt -out certs.der -outform DER
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.
quelle
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
echo '[ subject_alt_name ]' >> openssl.cnf
echo 'subjectAltName = DNS:example.mydomain1.com, DNS:example.mydomain2.com, DNS:example.mydomain3.com, DNS: localhost'>> openssl.cnf
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
Exportieren Sie die öffentliche Schlüsseldatei (.pem) in das PKS12-Format. Dadurch werden Sie zur Eingabe des Kennworts aufgefordert
Erstellen Sie a.JKS aus selbstsigniertem PEM (Keystore).
Generieren Sie ein Zertifikat aus der obigen Keystore- oder JKS-Datei
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.)
Ursprüngliche Antwort auf diesen Link hier gepostet .
quelle
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:
[BEARBEITEN]
Wie von conapart3 erwähnt,
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
ist 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.quelle
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
ist jetzt veraltet.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.
quelle
Habe es bereits unter https://stackoverflow.com/a/53491151/1909708 beantwortet .
Dies schlägt fehl, da weder der allgemeine Name des Zertifikats (
CN
in der ZertifizierungSubject
) noch einer der alternativen Namen (Subject Alternative Name
im 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 einencacerts
gemeinsamen 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
Oben wurde ein implementiertes
HostnameVerifier
Objekt übergeben, das immer zurückgegeben wirdtrue
:quelle
Für Spring Boot
RestTemplate
:org.apache.httpcomponents.httpcore
Abhängigkeit hinzufügenVerwendung
NoopHostnameVerifier
für SSL Factory:quelle
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.
quelle
quelle
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
quelle
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.
quelle
quelle
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.
quelle
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]
quelle
Ich habe das Problem folgendermaßen gelöst.
1. Eine Klasse erstellen. Die Klasse hat einige leere Implementierungen
2. Erstellen einer Methode
quelle