Fehler: Das erste Zertifikat in nodejs konnte nicht überprüft werden

141

Ich versuche, eine Datei mithilfe einer URL vom Jira-Server herunterzuladen, erhalte jedoch eine Fehlermeldung. So fügen Sie ein Zertifikat in den Code ein, um den Fehler zu überprüfen :

Error: unable to verify the first certificate in nodejs

at Error (native)
    at TLSSocket.<anonymous> (_tls_wrap.js:929:36)

  at TLSSocket.emit (events.js:104:17)

at TLSSocket._finishInit (_tls_wrap.js:460:8)

Mein Nodejs-Code:

var https = require("https");
var fs = require('fs');
var options = {
    host: 'jira.example.com',
    path: '/secure/attachment/206906/update.xlsx'
};

https.get(options, function (http_res) {

    var data = "";


    http_res.on("data", function (chunk) {

        data += chunk;
    });


    http_res.on("end", function () {

        var file = fs.createWriteStream("file.xlsx");
        data.pipe(file);

    });
});
Labeo
quelle
Konnten Sie das lösen?
Sharad Jain
1
Ich habe ein anderes Verfahren wie das Deaktivieren der Zertifikatsüberprüfung verwendet und fertig
Labeo
Können Sie etwas näher darauf eingehen? Dies wird wirklich hilfreich für mich sein
Sharad Jain
siehe unten Antwort für die Validierung des Zertifikats, das wir ablehnen müssenUnauthorized
Labeo

Antworten:

120

Versuchen Sie, das entsprechende Stammzertifikat hinzuzufügen

Dies wird immer eine viel sicherere Option sein, als nicht autorisierte Endpunkte blind zu akzeptieren, was wiederum nur als letztes Mittel verwendet werden sollte.

Dies kann so einfach wie das Hinzufügen sein

require('https').globalAgent.options.ca = require('ssl-root-cas/latest').create();

zu Ihrer Bewerbung.

Das npm-Paket der SSL-Stammzertifizierungsstellen (wie hier verwendet) ist ein sehr nützliches Paket in Bezug auf dieses Problem.

Joshua
quelle
9
Diese Antwort sollte in den meisten Fällen verwendet werden, da sie das Problem tatsächlich behebt und nicht den gesamten Nutzen von SSL deaktiviert.
Mikemaccana
12
Wie im README-Modul ssl-root-cas angegeben, besteht eine der häufigsten Ursachen für dieses Problem darin, dass in Ihr Zertifikat keine CA-Zwischenzertifikate eingebettet sind. Versuchen Sie, Ihr Zertifikat zu reparieren, bevor Sie etwas anderes versuchen;)
Laurent VB
Möglicherweise benötigen Sie nicht einmal das SSL-root-cas-Paket. Setzen Sie einfach das globalAgents.option.cert auf ein Vollkettenzertifikat. Das hat mein Problem gelöst.
smartexpert
1
mkcert erstellt kein "Fullchain" -Zertifikat. Sie müssen Ihr Zertifikat mit dem Stammzertifikat verknüpfen, das $(mkcert -CAROOT)/rootCA.pemin einer neuen Zertifikatdatei verfügbar ist, und so etwas wie https.globalAgent.options.ca = fs.readFileSync('fullchain.pem')Siehe github.com/FiloSottile/mkcert/issues/76
Frosty Z
Aus Sicherheitsgründen hat das ssl-root-casnpm-Modul eine Anfrage an mozilla.org hardcoded git.coolaj86.com/coolaj86/ssl-root-cas.js/src/branch/master/… . Es ist wahrscheinlich sicher, weil Mozilla, aber es scheint wie ein Angriffsvektor.
Avindra Goolcharan
60

Ein weiterer schmutziger Hack, der alle Ihre Anfragen unsicher macht:

process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0
Satara
quelle
8
Dies scheint nicht anders zu sein als Labeos Antwort oben , da es genauso gefährlich ist.
Ocramot
4
Es ist anders, es sind keine Codierungsänderungen erforderlich, da die env-Variable außerhalb des Quellcodes festgelegt werden kann.
Jzacharuk
1
Diese Antwort ist gefährlich. Sie deaktivieren alle von TLS bereitgestellten Sicherheitsfunktionen.
Flimm
1
Das hat bei mir funktioniert, super hilfreich. In meinem Fall spreche ich nur mit localhost , daher ist die Sicherheit nicht das Problem.
Mike S
Gut, nur um localhost zu testen. Stellen Sie einfach sicher, dass Sie es nach Ihren Tests entfernen.
Nico
44

Wenn das erste Zertifikat in nodejs nicht überprüft werden kann, ist eine nicht autorisierte Ablehnung erforderlich

 request({method: "GET", 
        "rejectUnauthorized": false, 
        "url": url,
        "headers" : {"Content-Type": "application/json",
        function(err,data,body) {
    }).pipe(
       fs.createWriteStream('file.html'));
Labeo
quelle
129
Diese Antwort ist gefährlich. Der andere ist sicherer.
Mikemaccana
3
Auf diese Weise entfernen Sie die von SSL bereitgestellte Sicherheit, sodass sie nur für die Entwicklung verwendet werden sollte.
Sylvain
11
Wenn Sie keine Zertifikate prüfen, können Sie sich der Identität der anderen Partei nicht sicher sein und sind daher möglicherweise einem gefälschten Host ausgesetzt. Selbst wenn Sie keine Zertifikate überprüfen, erhalten Sie dennoch eine verschlüsselte Kommunikation, die nicht (leicht) ausspioniert werden kann. Das Hinzufügen dieser Zeile "entfernt also nicht die Sicherheit" von SSL und, wie ein anderer Kommentator sagte, "deaktiviert [] den gesamten Nutzen von SSL".
Bob Pollack
4
Das Deaktivieren der SSL-Überprüfung ist KEINE Lösung für ein Problem. :-)
Siddhu
9
Dies funktioniert, wenn Sie die Knotenanforderungsbibliothek verwenden. Was ich bin. Und danke, es löst mein unmittelbares Entwicklungsbedürfnis.
Alan
29

Der Server, von dem Sie herunterladen möchten, ist möglicherweise schlecht konfiguriert. Selbst wenn es in Ihrem Browser funktioniert, enthält es möglicherweise nicht alle öffentlichen Zertifikate in der Kette, die ein Client mit leerem Cache zur Überprüfung benötigt.

Ich empfehle, die Website im SSLlabs-Tool zu überprüfen: https://www.ssllabs.com/ssltest/

Suchen Sie nach diesem Fehler:

Die Zertifikatkette dieses Servers ist unvollständig.

Und das:

Kettenprobleme ......... Unvollständig

Flimm
quelle
Ich erhalte dieses Problem (Kettenprobleme ......... unvollständig) für mein von DigiCert Inc. autorisiertes Zertifikat. Wie wird dieses Problem behoben?
Imarchuang
@imarchuang Kurz gesagt, Ihr Server muss nicht nur das Zertifikat für Ihre Domain, sondern auch die Zwischenzertifikate bereitstellen. Ich kann nicht mehr Details in diesen Kommentar einfügen, aber hoffentlich sind das genug Informationen, um Sie in die richtige Richtung zu weisen.
Flimm
Vielen Dank, wir haben es herausgefunden, indem wir auch das Root-Zertifikat gekämmt haben
imarchuang
Danke! Ich entdeckte, dass mein Zertifikat unvollständig war, obwohl es in Chrome und Firefox perfekt funktionierte, aber nicht in der Elektronen-App, und ich cat domainname.crt domainname.ca-bundle > domainname-ssl-bundle.crt
reparierte
25

unable to verify the first certificate

Die Zertifikatskette ist unvollständig.

Dies bedeutet, dass der Webserver, mit dem Sie eine Verbindung herstellen, falsch konfiguriert ist und das Zwischenzertifikat nicht in die an Sie gesendete Zertifikatkette aufgenommen hat.

Zertifikatskette

Es sieht höchstwahrscheinlich wie folgt aus:

  1. Serverzertifikat - Speichert ein von einem Zwischenprodukt signiertes Zertifikat.
  2. Zwischenzertifikat - Speichert ein von root signiertes Zertifikat.
  3. Stammzertifikat - speichert ein selbstsigniertes Zertifikat.

Das Zwischenzertifikat sollte zusammen mit dem Serverzertifikat auf dem Server installiert sein.
Stammzertifikate sind in Softwareanwendungen, Browser und Betriebssysteme eingebettet.

Die Anwendung, die das Zertifikat bereitstellt, muss die gesamte Kette senden, dh das Serverzertifikat selbst und alle Zwischenprodukte. Das Stammzertifikat soll dem Client bekannt sein.

Erstellen Sie das Problem neu

Gehen Sie mit Ihrem Browser zu https://incomplete-chain.badssl.com .

Es wird kein Fehler angezeigt (Vorhängeschloss in der Adressleiste ist grün).
Dies liegt daran, dass Browser dazu neigen, die Kette zu vervollständigen, wenn sie nicht vom Server gesendet werden.

Stellen Sie nun über den Knoten eine Verbindung zu https://incomplete-chain.badssl.com her :

// index.js
const axios = require('axios');

axios.get('https://incomplete-chain.badssl.com')
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

Protokolle: " Fehler: Das erste Zertifikat kann nicht überprüft werden ".

Lösung

Sie müssen die Zertifikatskette selbst ausfüllen.

Das zu tun:

1:.pem Dann müssen Sie das fehlende Zwischenzertifikat im Format erhalten

2a: Erweitern Sie den integrierten Zertifikatspeicher des Knotens mit NODE_EXTRA_CA_CERTS:

2b: oder übergeben Sie Ihr eigenes Zertifikatspaket (Zwischenprodukte und Root) mit der caOption.

1. Wie bekomme ich ein Zwischenzertifikat?

Verwenden openssl(wird mit Git für Windows geliefert ).

Speichern Sie die Zertifikatdetails des Remote-Servers:

openssl s_client -connect incomplete-chain.badssl.com:443 -servername incomplete-chain.badssl.com | tee logcertfile

Wir suchen den Aussteller (das Zwischenzertifikat ist der Aussteller / Unterzeichner des Serverzertifikats):

openssl x509 -in logcertfile -noout -text | grep -i "issuer"

Es sollte Ihnen die URI des Signaturzertifikats geben. Lade es herunter:

curl --output intermediate.crt http://cacerts.digicert.com/DigiCertSHA2SecureServerCA.crt

Konvertieren Sie es schließlich in .pem:

openssl x509 -inform DER -in intermediate.crt -out intermediate.pem -text

2a. NODE_EXTRA_CERTS

Ich verwende cross-env , um Umgebungsvariablen in der package.jsonDatei festzulegen:

"start": "cross-env NODE_EXTRA_CA_CERTS=\"C:\\Users\\USERNAME\\Desktop\\ssl-connect\\intermediate.pem\" node index.js"

2b. caMöglichkeit

Diese Option überschreibt die integrierten Stammzertifizierungsstellen des Knotens.

Deshalb müssen wir unsere eigene Stammzertifizierungsstelle erstellen. Verwenden Sie ssl-root-cas .

Erstellen Sie dann einen benutzerdefinierten httpsAgenten, der mit unserem Zertifikatspaket (Root und Intermediate) konfiguriert ist. Übergeben Sie diesen Agenten an, axioswenn Sie eine Anfrage stellen.

// index.js
const axios = require('axios');
const path = require('path');
const https = require('https');
const rootCas = require('ssl-root-cas').create();

rootCas.addFile(path.resolve(__dirname, 'intermediate.pem'));
const httpsAgent = new https.Agent({ca: rootCas});

axios.get('https://incomplete-chain.badssl.com', { httpsAgent })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

Anstatt einen benutzerdefinierten httpsAgenten zu erstellen und an diesen zu übergeben axios, können Sie die Zertifikate auf dem httpsglobalen Agenten platzieren:

// Applies to ALL requests (whether using https directly or the request module)
https.globalAgent.options.ca = rootCas;

Ressourcen:

  1. https://levelup.gitconnected.com/how-to-resolve-certificate-errors-in-nodejs-app-involving-ssl-calls-781ce48daded
  2. https://www.npmjs.com/package/ssl-root-cas
  3. https://github.com/nodejs/node/issues/16336
  4. https://www.namecheap.com/support/knowledgebase/article.aspx/9605/69/how-to-check-ca-chain-installation
  5. /superuser/97201/how-to-save-a-remote-server-ssl-certificate-locally-as-a-file/
  6. So konvertieren Sie .crt in .pem
sch
quelle
Sehr detaillierte Erklärung.
Sieben
Einfach unglaublich! Hat bei mir nicht funktioniert, aber was für ein Detail!
Tom Chadaravicius
6

Dies löste es tatsächlich für mich unter https://www.npmjs.com/package/ssl-root-cas

// INCORRECT (but might still work)
var server = https.createServer({
  key: fs.readFileSync('privkey.pem', 'ascii'),
  cert: fs.readFileSync('cert.pem', 'ascii') // a PEM containing ONLY the SERVER certificate
});

// CORRECT (should always work)
var server = https.createServer({
  key: fs.readFileSync('privkey.pem', 'ascii'),
  cert: fs.readFileSync('fullchain.pem', 'ascii') // a PEM containing the SERVER and ALL INTERMEDIATES
});
Koolaang
quelle
1
Das ist imho die beste Lösung, da es keine zusätzlichen Bibliotheken erfordert und einfach ist
Martin Schneider
4

Möglicherweise können Sie dies tun, indem Sie die Anforderungsoptionen wie folgt ändern. Wenn Sie ein selbstsigniertes Zertifikat oder einen fehlenden Vermittler verwenden, wird durch das Setzen von strictSSL auf false das Anforderungspaket nicht zur Validierung des Zertifikats gezwungen.

var options = {
   host: 'jira.example.com',
   path: '/secure/attachment/206906/update.xlsx',
   strictSSL: false
}
Sundar
quelle
Dies hat mein Problem gelöst. Ich verwende das Modul 'request' anstelle des Moduls 'http'. Vielen Dank!
Bruno Nunes
2

GoDaddy SSL CCertificate

Ich habe dies erlebt, als ich versucht habe, mit dem GoDaddy-Zertifikat eine Verbindung zu unserem Backend-API-Server herzustellen. Hier ist der Code, mit dem ich das Problem gelöst habe.

var rootCas = require('ssl-root-cas/latest').create();

rootCas
  .addFile(path.join(__dirname, '../config/ssl/gd_bundle-g2-g1.crt'))
  ;

// will work with all https requests will all libraries (i.e. request.js)
require('https').globalAgent.options.ca = rootCas;

PS:

Verwenden Sie das mitgelieferte Zertifikat und vergessen Sie nicht, die Bibliothek zu installieren npm install ssl-root-cas

Dean Christian Armada
quelle
1
Dies funktionierte für mich mit der Ausnahme, dass ich beim Importieren "ssl-root-cas" anstelle von "ssl-root-cas / latest" verwenden musste.
krishnan
2

Dies funktionierte für mich => Hinzufügen eines Agenten und 'RejectUnauthorized' auf false gesetzt

const https = require('https'); //Add This
const bindingGridData = async () => {
  const url = `your URL-Here`;
  const request = new Request(url, {
    method: 'GET',
    headers: new Headers({
      Authorization: `Your Token If Any`,
      'Content-Type': 'application/json',
    }),
    //Add The Below
    agent: new https.Agent({
      rejectUnauthorized: false,
    }),
  });
  return await fetch(request)
    .then((response: any) => {
      return response.json();
    })
    .then((response: any) => {
      console.log('response is', response);
      return response;
    })
    .catch((err: any) => {
      console.log('This is Error', err);
      return;
    });
};

Vigneshwaran Ethirajan
quelle
1

Ein anderer Ansatz, um dies zu lösen, ist die Verwendung des folgenden Moduls.

node_extra_ca_certs_mozilla_bundle

Dieses Modul kann ohne Codeänderung arbeiten, indem eine PEM-Datei generiert wird, die alle von Mozilla vertrauenswürdigen Stamm- und Zwischenzertifikate enthält. Sie können die folgende Umgebungsvariable verwenden (funktioniert mit Nodejs v7.3 +):

NODE_EXTRA_CA_CERTS

So generieren Sie die PEM-Datei zur Verwendung mit der obigen Umgebungsvariablen. Sie können das Modul installieren mit:

npm install --save node_extra_ca_certs_mozilla_bundle

Starten Sie dann Ihr Knotenskript mit einer Umgebungsvariablen.

NODE_EXTRA_CA_CERTS=node_modules/node_extra_ca_certs_mozilla_bundle/ca_bundle/ca_intermediate_root_bundle.pem node your_script.js

Weitere Möglichkeiten zur Verwendung der generierten PEM-Datei finden Sie unter:

https://github.com/arvind-agarwal/node_extra_ca_certs_mozilla_bundle

HINWEIS: Ich bin der Autor des obigen Moduls.

arva
quelle
-3

Ich habe das Nodemailer npm-Modul verwendet. Der folgende Code hat das Problem behoben

     tls: {
     // do not fail on invalid certs
     rejectUnauthorized: false
     }
Chandru
quelle