Cum se rezolvă problema „java.security.cert.CertificateException: Nu există nume alternative de subiect prezente”? (Programare, Java, Ssl, Https, Certificat, Certificat Ssl)

Mentiflectax a intrebat.

Am un client de servicii web Java, care consumă un serviciu web prin 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);
    }

Atunci când mă conectez la URL-ul serviciului (https://AAA.BBB.CCC.DDD:9443/ISomeService ), primesc excepția java.security.cert.CertificateException: No subject alternative names present.

Pentru a remedia problema, am rulat mai întâi openssl s_client -showcerts -connect AAA.BBB.CCC.DDD:9443 > certs.txt și am obținut următorul conținut în fișier 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, acum trebuie să

  1. să extrag partea de certs.txt între -----BEGIN CERTIFICATE----- și -----END CERTIFICATE-----,
  2. să o modific astfel încât numele certificatului să fie egal cu AAA.BBB.CCC.DDD și
  3. apoi importați rezultatul folosind keytool -importcert -file fileWithModifiedCertificate (unde fileWithModifiedCertificate este rezultatul operațiilor 1 și 2).

Este corect acest lucru?

În caz afirmativ, cum anume pot face ca certificatul de la pasul 1 să funcționeze cu adrese IP (AAA.BBB.CCC.DDD) ?

Actualizare 1 (23.10.2013 15:37 MSK): Într-un răspuns la o întrebare similară, am citit următoarele:

Dacă nu dețineți controlul asupra serverului respectiv, utilizați numele de gazdă al acestuia (cu condiția să existe cel puțin un CN care să corespundă acelui nume de gazdă în certificatul existent).

Ce înseamnă mai exact „folosiți”?

Comentarii

  • Răspunde acest lucru la întrebarea dumneavoastră? Rezolvarea javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed Error? –  > Por rogerdpack.
21 răspunsuri
Mentiflectax

Am rezolvat problema prin dezactivarea verificărilor HTTPS folosind abordarea prezentată aici:

Am pus următorul cod în fișierul ISomeService clasă:

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

Din moment ce folosesc clasa https://AAA.BBB.CCC.DDD:9443/ISomeService doar în scopuri de testare, este o soluție suficient de bună, dar nu faceți acest lucru în producție.

Rețineți că puteți, de asemenea, să dezactivați SSL pentru „o conexiune la un moment dat”, de exemplu:

 // don't call disableSslVerification but use its internal code:
 HttpURLConnection conn = (HttpURLConnection) url.openConnection();
 if (conn instanceof HttpsURLConnection) {
    HttpsURLConnection httpsConn = (HttpsURLConnection) conn;
    httpsConn.setHostnameVerifier(allHostsValid);
    httpsConn.setSSLSocketFactory(sc.getSocketFactory());
 }

Comentarii

  • Abordarea menționată în link-ul menționat mai sus pare să fie blocată (nakov.com/blog/2009/07/16/…) . Poate cineva să actualizeze link-ul ? –  > Por John.
  • Am încercat să dezactivez validarea făcând acest proces, dar validarea browserului pentru protocoalele SSL (vulnerabilitatea Poodle) îmi dă: ssl_error_no_cypher_overlap. Aveți vreo idee? –  > Por will824.
  • Bună ziua, primesc org.springframework.web.client.HttpClientErrorException: 403 Forbidden – user5268786
  • 86

  • dezactivarea verificării HTTPS nu este o „soluție”. Ar trebui să spuneți că am găsit un „patch”. –  > Por Jus12.
  • Acest lucru va cauza vulnerabilitate pe Pre_prod și Production. 1. 1. Faceți o intrare de gazdă în fișierul gazdă Windows 2. Sau adăugați nume IP sau FQDN în câmpurile Subject alternative names (Nume alternative pentru subiect) din certificatele –  > Por Shankar.
juanmhidalgo

Am aceeași problemă și am rezolvat-o cu acest cod. am pus acest cod înainte de primul apel la serviciile mele web.

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

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

Este simplu și funcționează bine.

Aici este sursa originală.

Comentarii

  • Sau ai putea înlocui întregul corp al funcției verify() cu return hostname.equals("localhost");, dacă asta este ceea ce doriți să faceți. if este complet superfluă. –  > Por utilizator.
  • Aceasta a fost o soluție simplă și rapidă care ne-a permis să ocolim testarea în mediul de testare al unui furnizor care nu avea un certificat corespunzător. Vă mulțumim mult! –  > Por dacDave.
  • @JuanM.Hidalgo, care a funcționat pentru mine, a plasat codul de mai sus chiar înainte de apelul către HttpsURLConnection connection = (HttpsURLConnection) obj.openConnection();. De asemenea, acest lucru ignoră fiecare certificat? Din moment ce am văzut că o astfel de soluție de lucru este vulnerabilă la securitate. Vă mulțumesc! –  > Por ThunderWiring.
  • acest răspuns a rezolvat excepția mea SSL cert și problema caracterelor non LDH, am putut vedea că există un bug raportat în JDK deschis, bugs.openjdk.java.net/browse/JDK-8170265 –  > Por Akhil S Kamath.
  • Funcționează, deși continuă cu o altă eroare, dezactivarea SSL în întregime a funcționat în cele din urmă stackoverflow.com/a/19542614/32453 –  > Por rogerdpack.
Markus

Aceasta este o întrebare veche, totuși am avut aceeași problemă atunci când am trecut de la JDK 1.8.0_144 la jdk 1.8.0_191

Am găsit un indiciu în changelog:

Changelog

am adăugat următoarea proprietate de sistem suplimentară, care ne-a ajutat în cazul nostru să rezolvăm această problemă:

-Dcom.sun.jndi.ldap.object.disableEndpointIdentification=true

Comentarii

  • este o nebunie, dar nimeni în viață nu știe ce previne de fapt verificarea pe care o fac. doar inginerii adaugă lucruri pentru că au citit pe un blog thoughtworks –  > Por bharal.
Bruno

Verificarea identității certificatului se face în funcție de ceea ce solicită clientul.

Atunci când clientul utilizează https://xxx.xxx.xxx.xxx/something (unde xxx.xxx.xxx.xxx este o adresă IP), identitatea certificatului este verificată în raport cu această adresă IP (în teorie, doar folosind o extensie IP SAN).

Dacă certificatul dvs. nu are IP SAN, ci DNS SAN (sau dacă nu are DNS SAN, un nume comun în Subject DN), puteți face ca acest lucru să funcționeze dacă clientul dvs. utilizează în schimb un URL cu acel nume de gazdă (sau un nume de gazdă pentru care certificatul ar fi valabil, dacă există mai multe valori posibile). De exemplu, dacă certificatul dumneavoastră are un nume pentru www.example.com, utilizați https://www.example.com/something.

Bineînțeles, veți avea nevoie ca acel nume de gazdă să se rezolve la acea adresă IP.

În plus, în cazul în care există SAN-uri DNS, CN din Subject DN va fi ignorat, așa că, în acest caz, utilizați un nume care să corespundă unuia dintre SAN-urile DNS.

Comentarii

  • Nu pot accesa serviciul prin http://www.example.com/someservice. Este corect ca, pentru ca certificatul să funcționeze cu adresa bazată pe IP (https://AAA.BBB.CCC.DDD:9443/ISomeService), trebuie să setez toate CN câmpurile la AAA.BBB.CCC.DDD (înlocuiți someSubdomain.someorganisation.com cu AAA.BBB.CCC.DDD în fișierul de mai sus) și să importe fișierul certificat rezultat? –  > Por Mentiflectax.
  • Nu puteți face nimic cu privire la CN sau la certificat dacă nu dețineți controlul asupra serverului. –  > Por Bruno.
  • pentru a avea acces la adresa ip în scopuri de testare, puteți modifica temporar adresa dvs. /etc/hosts sau un fișier echivalent –  > Por tyoc213.
  • În codul meu trimiteam cererea către un IP public, dar CN-ul certificatului era un nume de gazdă. Deci, în codul meu, am înlocuit IP-ul cu numele de gazdă și mi-am configurat /etc/hosts pentru a asocia acest nume de gazdă la IP. Rezolvat! –  > Por Leopold Gault.
andreycpp

Pentru a importa cert:

  1. Extrageți cert-ul de pe server, de ex. openssl s_client -showcerts -connect AAA.BBB.CCC.DDD:9443 > certs.txt Acest lucru va extrage certificatele în format PEM.
  2. Convertiți cert-ul în format DER, deoarece acest lucru este ceea ce așteaptă keytool, de ex. openssl x509 -in certs.txt -out certs.der -outform DER
  3. Acum doriți să importați acest cert în fișierul „cacert” implicit al sistemului. Localizați fișierul „cacerts” implicit al sistemului pentru instalarea Java. Aruncați o privire la How to obtain the location of cacerts of the default java installation?
  4. Importați certificatele în acel fișier cacerts: sudo keytool -importcert -file certs.der -keystore <path-to-cacerts> Parola implicită pentru cacerts este „changeit”.

Dacă certificatul este emis pentru un FQDN și încercați să vă conectați prin adresa IP în codul Java, atunci probabil că acest lucru ar trebui să fie rezolvat în codul dvs. mai degrabă decât să interveniți asupra certificatului în sine. Schimbați-vă codul pentru a vă conecta prin FQDN. Dacă FQDN nu poate fi rezolvat pe calculatorul de dezvoltare, adăugați-l pur și simplu la fișierul hosts sau configurați-vă calculatorul cu un server DNS care poate rezolva acest FQDN.

Comentarii

  • „Dacă FQDN nu poate fi rezolvat pe mașina de dezvoltare, adăugați-l pur și simplu la fișierul hosts” – a ajutat. Vă mulțumim mult! –  > Por Woland.
  • Am făcut același lucru, dar totuși, problema persistă. Se mai poate face ceva folosind această abordare? –  > Por pkgajulapalli.
Abhishek Galoda

Am rezolvat această problemă într-un mod corect adăugând numele alt subiect în certificat, mai degrabă decât să fac modificări în cod sau să dezactivez SSL, spre deosebire de ceea ce alte răspunsuri sugerează aici. Dacă vedeți în mod clar, excepția spune că „Subject alt names are missing”, deci modul corect ar trebui să fie adăugarea lor

Vă rugăm să vă uitați la acest lucru link pentru a înțelege pas cu pas.

Eroarea de mai sus înseamnă că din fișierul JKS lipsește domeniul necesar pe care încercați să accesați aplicația. va trebui să Utilizați Open SSL și instrumentul cheie pentru a adăuga mai multe domenii

  1. Copiați openssl.cnf într-un director curent
  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. Să exportați fișierul cu cheia publică (.pem) în format PKS12. Acest lucru vă va solicita parola

    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. Creați un fișier .JKS din PEM auto-semnat (Keystore)

    keytool -importkeystore -destkeystore keystore.jks -deststoretype PKCS12 -srcstoretype PKCS12 -srckeystore keystore.p12
    
  7. Generați un certificat din fișierul Keystore sau JKS de mai sus

    keytool -export -keystore keystore.jks -alias myalias -file selfsigned.crt
    
  8. Deoarece certificatul de mai sus este semnat de sine stătător și nu este validat de CA, acesta trebuie adăugat în Truststore (fișierul Cacerts în locația de mai jos pentru MAC, pentru Windows, aflați unde este instalat JDK-ul dvs.).

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

Răspuns original postat pe acest link aici.

lifesoordinary

Este posibil să nu doriți să dezactivați toate Verificarea ssl și, prin urmare, puteți dezactiva doar verificarea hostName prin acest lucru, care este un pic mai puțin înfricoșător decât alternativa:

HttpsURLConnection.setDefaultHostnameVerifier(
    SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

[EDIT]

După cum a menționat conapart3 SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER este acum depreciat, așa că ar putea fi eliminat într-o versiune ulterioară, astfel încât s-ar putea să fiți forțat în viitor să vă faceți propria listă, deși aș spune în continuare că m-aș îndepărta de orice soluție în care toată verificarea este dezactivată.

Comentarii

  • SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER este acum depășită. –  > Por bonapart3.
Shahriar

problema mea cu obținerea acestei erori a fost rezolvată prin utilizarea URL-ului complet „qatest.ourCompany.com/webService” în loc de doar „qatest/webService”. Motivul a fost că certificatul nostru de securitate avea un wildcard, adică „*.ourCompany.com”. Odată ce am introdus adresa completă, excepția a dispărut. Sper să vă fie de ajutor.

Himadri Pant

Am răspuns deja la această întrebare în https://stackoverflow.com/a/53491151/1909708.

Acest lucru eșuează deoarece nici numele comun al certificatului (CN în certificare Subject), nici niciunul dintre numele alternative (Subject Alternative Name din certificat) se potrivesc cu numele de gazdă sau adresa IP țintă.

De exemplu, de la un JVM, atunci când se încearcă conectarea la o adresă IP (WW.XX.YY.ZZ) și nu la numele DNS (https://stackoverflow.com), conexiunea HTTPS va eșua deoarece certificatul stocat în java truststore cacerts se așteaptă ca numele comun (sau numele alternativ al certificatului, cum ar fi stackexchange.com sau *.stackoverflow.com etc.) să corespundă cu adresa țintă.

Vă rugăm să verificați: 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();

Mai sus, a fost trecut un fișier implementat HostnameVerifier care returnează întotdeauna true:

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

Grigory Kislin

Pentru Spring Boot RestTemplate:

  • adăugați org.apache.httpcomponents.httpcore dependență
  • utilizați NoopHostnameVerifier pentru fabrica 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);
    

animo3991

M-am confruntat, de asemenea, cu aceeași problemă cu un certificat autofirmat . Referindu-mă la câteva dintre soluțiile de mai sus, am încercat să regenerez certificatul cu CN-ul corect, adică adresa IP a serverului, dar tot nu a funcționat pentru mine. în cele din urmă am încercat să regenerez certificatul adăugând adresa SAN la acesta prin comanda menționată mai jos

**keytool -genkey -keyalg RSA -keystore keystore.jks -keysize 2048 -alias <IP_ADDRESS> -ext san=ip:<IP_ADDRESS>**

După aceea, am pornit serverul și am descărcat certificatele clienților prin comanda openssl menționată mai jos.

**openssl s_client -showcerts -connect <IP_ADDRESS>:443 < /dev/null | openssl x509 -outform PEM > myCert.pem**

Apoi am importat acest certificat de client în fișierul Java keystore implicit (cacerts) al mașinii mele client prin comanda menționată mai jos

**keytool -import -trustcacerts -keystore /home/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-1.el7.x86_64/jre/lib/security/cacerts -alias <IP_ADDRESS> -file ./mycert.pem**

Comentarii

  • Adăugarea „-ext ip:<IP_ADDRESS>” în comanda keytool genkey rezolvă problema. Vă rugăm să rețineți că atunci când keytools cere numele și prenumele, trebuie să introduceți și răspunsul <IP_ADDRESS> pentru a genera cert. –  > Por Raymond Chiu.
Gert

Am ajuns la această întrebare după ce dacă am primit același mesaj de eroare. Cu toate acestea, în cazul meu aveam două URL-uri cu subdomenii diferite (http://example1.xxx.com/someservice și http://example2.yyy.com/someservice) care erau direcționate către același server. Acest server avea un singur certificat wildcard pentru domeniul *.xxx.com. La utilizarea serviciului prin intermediul celui de-al doilea domeniu, certificatul găsit (*.xxx.com) nu se potrivește cu domeniul solicitat (*.yyy.com) și apare eroarea.

În acest caz, nu trebuie să încercăm să rezolvăm un astfel de mesaj de eroare prin reducerea securității SSL, ci trebuie să verificăm serverul și certificatele de pe acesta.

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

Comentarii

  • vă rugăm să adăugați un text explicativ la codul dvs. Consultați stackoverflow.com/help/how-to-answer –  > Por jasie.
  • Acesta este un defect de securitate. Acesta este modul în care se dezactivează verificarea certificatelor în primul rând. Toți cei care copiază această soluție vor crea un bug de securitate în software-ul lor. –  > Por Marek Puchalski.
Sachin Rane

Treceam prin 2 way SSL în springboot. Am făcut toate configurările corecte pentru serviciul Tomcat Server și pentru serviciul RestTemplate, dar am primit o eroare de tipul „java.security.cert.CertificateException: Nu există nume alternative de subiect prezente”

După ce am trecut prin soluții, am constatat că JVM are nevoie de acest certificat, altfel dă o eroare de handshaking.

Acum, cum să adaug acest lucru la JVM.

mergeți la fișierul jre/lib/security/cacerts. trebuie să adăugăm fișierul de certificat al serverului nostru la acest fișier cacerts din jvm.

Comandă pentru a adăuga serverul cert la fișierul cacerts prin linia de comandă în Windows.

C:Program FilesJavajdk1.8.0_191jrelibsecurity>keytool -import -noprompt -trustcacerts -alias sslserver -file E:spring_cloud_sachinssl_keyssslserver.cer -keystore cacerts -storepass changeit

Verificați dacă cert-ul serverului este instalat sau nu:

C:Program FilesJavajdk1.8.0_191jrelibsecurity>keytool -list -keystore cacerts

puteți vedea lista de certificate instalate:

pentru mai multe detalii: https://sachin4java.blogspot.com/2019/08/javasecuritycertcertificateexception-no.html

manoj

adăugați intrarea host cu ip-ul corespunzător CN-ului din certificat

CN=someSubdomain.someorganisation.com

acum actualizați ip-ul cu numele CN în care încercați să accesați url-ul.

Pentru mine a funcționat.

Nizam Mahammad

Acest cod va funcționa ca un farmec și va utiliza obiectul restTemple pentru restul codului.

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

Tudor

Atunci când aveți un certificat cu CN și Subject Alternative Names (SAN), dacă faceți o cerere bazată pe conținutul CN, atunci conținutul respectiv trebuie să fie prezent și în SAN, altfel va eșua cu eroarea în cauză.

În cazul meu CN avea ceva, SAN avea altceva. A trebuit să folosesc SAN URL, iar apoi a funcționat foarte bine.

Manishoaham

Am rezolvat problema menționată

MqttException (0) – javax.net.ssl.SSLHandshakeException: NosubjectAltNames de pe certificat se potrivesc.

adăugând un nume de subiect alternativ (se pot adăuga mai multe) în certificatul serverului (având CN=exemple.com) care, după ce a imprimat partea de certificat ca mai jos:

Subject Alternative Name:
DNS: example.com

Am folosit KeyExplorer pe Windows pentru generarea certificatului meu de server.Puteți urmări acest link pentru a adăuga nume de subiect alternative (urmați doar partea de adăugare).

Shehan Simen

După cum a arătat cineva înainte, am adăugat următorul cod (cu lambda) chiar înainte de a crea obiectul RestTemplate și funcționează bine. IT este doar pentru clasa mea de testare internă, așa că voi lucra cu o soluție mai bună pentru codul de producție.

javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
            (hostname, sslSession) -> true);

Prakash Soni

Adăugați adresa dvs. de IP în fișierul hosts.care se află în folderul C:WindowsSystem32driversetc. De asemenea, adăugați IP și numele de domeniu al adresei IP.exemplu:aaa.bbb.ccc.ddd [email protected]

Aditya Bhuyan

Am rezolvat problema în felul următor.

1. Crearea unei clase . Clasa are câteva implementări goale

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. Crearea unei metode

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. Se apelează metoda disableSSL() în care este aruncată excepția. A funcționat bine.