Comment fixer le "java.sécurité.cert.CertificateException: aucun sujet noms alternatifs présents " erreur?
j'ai un client Java web service, qui consomme un service web via 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);
}
quand je me connecte à L'URL du service ( https://AAA.BBB.CCC.DDD:9443/ISomeService
), j'obtiens l'exception java.security.cert.CertificateException: No subject alternative names present
.
pour le corriger, j'ai d'abord couru openssl s_client -showcerts -connect AAA.BBB.CCC.DDD:9443 > certs.txt
et obtenu le contenu suivant dans le fichier 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)
---
autant que je sache, maintenant, j'ai besoin de
- extraire la partie de
certs.txt
entre-----BEGIN CERTIFICATE-----
et-----END CERTIFICATE-----
, - Modifier pour que le nom du certificat soit égal à
AAA.BBB.CCC.DDD
et - puis importer le résultat en utilisant
keytool -importcert -file fileWithModifiedCertificate
(oùfileWithModifiedCertificate
est le résultat des opérations 1 et 2).
est-ce correct?
si oui, comment faire fonctionner le certificat de l'étape 1 avec adddress basé sur IP ( AAA.BBB.CCC.DDD
) ?
mise à jour 1 (23.10.2013 15: 37 MSK): dans une réponse à une question similaire , je lis ce qui suit:
si vous n'avez pas le contrôle de ce serveur, utilisez son nom d'hôte (à condition QU'il y a au moins un CN correspondant à ce nom d'hôte dans le cert).
Que signifie exactement "?
9 réponses
j'ai corrigé le problème en désactivant les vérifications HTTPS en utilisant l'approche présentée ici :
j'ai mis le code suivant dans la classe ISomeService
:
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();
}
}
comme j'utilise le https://AAA.BBB.CCC.DDD:9443/ISomeService
uniquement pour les tests, c'est une bonne solution.
j'ai le même problème et résolu avec ce code. J'ai mis ce code avant le premier appel à mes services.
javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
new javax.net.ssl.HostnameVerifier(){
public boolean verify(String hostname,
javax.net.ssl.SSLSession sslSession) {
return hostname.equals("localhost");
}
});
c'est simple et ça marche très bien.
ici est la source originale.
la vérification de l'identité du certificat est effectuée par rapport à ce que le client demande.
lorsque votre client utilise https://xxx.xxx.xxx.xxx/something
(où xxx.xxx.xxx.xxx
est une adresse IP), l'identité du certificat est vérifiée par rapport à cette adresse IP (en principe, seulement en utilisant une extension IP SAN).
si votre certificat n'a pas D'IP SAN, mais DNS SANs (ou si pas de DNS SAN, un nom commun dans le DN sujet), vous pouvez faire fonctionner cela en faisant utiliser à votre client une URL avec ce nom d'hôte au lieu (ou un nom d'hôte pour qui le cert serait valide, s'il y a plusieurs valeurs possibles). Par exemple , si vous avez un nom pour www.example.com
, utilisez https://www.example.com/something
.
bien sûr, vous aurez besoin de ce nom d'hôte pour vous résoudre à cette adresse IP.
de plus, s'il y a un Dns SANs, le CN dans le DN en question sera ignoré, donc utilisez un nom qui correspond à l'un des DNS SANs dans ce cas.
pour importer le cert:
- extraire le cert du serveur, par exemple
openssl s_client -showcerts -connect AAA.BBB.CCC.DDD:9443 > certs.txt
cela extraira les Cert au format PEM. - convertir le cert en format DER car c'est ce que keytool attend, par exemple
openssl x509 -in certs.txt -out certs.der -outform DER
- maintenant vous voulez importer ce cert dans le fichier 'cacert' par défaut du système. Localisez le fichier 'cacerts' par défaut du système pour votre installation Java. Jetez un oeil à Comment obtenir la localisation des cacerts de l'installation java par défaut?
- importer les certs dans ce fichier cacerts:
sudo keytool -importcert -file certs.der -keystore <path-to-cacerts>
mot de passe cacerts par défaut est 'changeit'.
si le cert est émis pour un FQDN et que vous essayez de vous connecter par adresse IP dans votre code Java, alors cela devrait probablement être corrigé dans votre code plutôt que de jouer avec le certificat lui-même. Changez votre code pour vous connecter par FQDN. Si FQDN n'est pas résolvable sur votre dev machine, il suffit de l'ajouter à votre fichier hosts, ou configurer votre machine avec le serveur DNS qui peut résoudre ce FQDN.
mon problème avec l'obtention de cette erreur a été résolu en utilisant L'URL complète "qatest.ourCompany.com/webService" au lieu de simplement "qatest / webService". La raison en était que notre certificat de sécurité comportait un caractère de remplacement, c'est-à-dire"*".ourCompany.com". Une fois que j'ai mis l'adresse complète, l'exception a disparu. Espérons que cette aide.
vous pouvez ne pas vouloir désactiver toute verification ssl et donc vous pouvez juste désactiver la vérification du nom d'hôte via ceci qui est un peu moins effrayant que l'alternative:
HttpsURLConnection.setDefaultHostnameVerifier(
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
[EDIT]
comme mentionné par conapart3 SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
est maintenant déprécié, de sorte qu'il peut être supprimé dans une version ultérieure, de sorte que vous pouvez être forcé dans le futur à rouler votre propre, bien que je dirais encore que je serais détourner de toutes les solutions où toute la vérification est éteindre.
j'ai corrigé cette question de manière correcte en ajoutant les noms alt des sujets dans le certificat plutôt que d'apporter des changements dans le code ou de désactiver SSL contrairement à ce que d'autres réponses suggèrent ici. Si vous voyez clairement l'exception dit "les noms alt Suject sont manquants" alors la bonne façon devrait être de les ajouter
s'il vous Plaît regarder cette lien à comprendre, étape par étape .
l'erreur ci-dessus signifie que votre fichier JKS manque le domaine requis sur lequel vous tentez d'accéder à l'application.Vous aurez besoin D'utiliser Open SSL et l'outil clé pour ajouter plusieurs domaines
- Copie de la openssl.cnf dans un répertoire courant
-
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/emailAddress=postmaster@example.com' -days 365
-
exporter la clé publique (.pem) au format PKS12. Cela vous demandera le mot de passe
openssl pkcs12 -export -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -export -in self-signed.pem -inkey private.key -name myalias -out keystore.p12
-
créer un.JKS from self-signed PEM (Keystore)
keytool -importkeystore -destkeystore keystore.jks -deststoretype PKCS12 -srcstoretype PKCS12 -srckeystore keystore.p12
-
Générer un Certificat à partir de ci-dessus de magasin de clés ou JKS fichier
keytool -export -keystore keystore.jks -alias myalias -file selfsigned.crt
-
comme le certificat ci-dessus est auto-signé et n'est pas validé par CA, il doit être ajouté dans le fichier Trustststststore(Cacerts dans le fichier ci-dessous pour MAC, Pour Windows, Découvrez où votre JDK est installé.)
sudo keytool -importcert -file selfsigned.crt -alias myalias -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/security/cacerts
réponse Originale à cette question posté sur ce lien ici .
j'ai résolu le problème de la façon suivante.
1. La création d'une classe . La classe A quelques implémentations vides
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. Création d'une méthode
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();
}
}
- appelez la méthode disableSSL () où l'exception est lancée. Il a bien fonctionné.
ajoutez votre adresse IP dans le fichier hosts.qui est dans le dossier de C:\Windows\System32\drivers\etc. Ajoutez également L'adresse IP et le nom de domaine de l'adresse IP. exemple: AAA.BBB.ccc.ddd abc@def.com