Blattsignatur kann nicht überprüft werden

142

Ich benutze node.js request.js, um eine API zu erreichen. Ich erhalte diesen Fehler

[Fehler: UNABLE_TO_VERIFY_LEAF_SIGNATURE]

Alle meine Anmeldeinformationen sind korrekt und gültig, und der Server ist in Ordnung. Ich habe die gleiche Anfrage mit dem Postboten gemacht.

request({
    "url": domain+"/api/orders/originator/"+id,
    "method": "GET",
    "headers":{
        "X-API-VERSION": 1,
        "X-API-KEY": key
    },
}, function(err, response, body){
    console.log(err);
    console.log(response);
    console.log(body);
});

Dieser Code wird nur in einem ausführbaren Skript ausgeführt. node ./run_file.js, Ist das Warum? Muss es auf einem Server ausgeführt werden?

ThomasReggi
quelle
Dies ist ein langer Weg, aber könnte es sein, dass die API den Benutzeragenten, der von Ihrem Knotenprogramm übergeben wird, nicht erkennt?
Hector Correa
@HectorCorrea Ich konnte die API in Postman perfekt lesen. Warum kann Node das nicht? Ich habe versucht, den Benutzeragenten zu wechseln, kein Glück.
Thomas Reggi

Antworten:

157

Hinweis : Folgendes ist gefährlich und ermöglicht das Abfangen und Ändern von API-Inhalten zwischen dem Client und dem Server.

Das hat auch funktioniert

process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';

ThomasReggi
quelle
22
Ich habe dies geändert und danke für die Antwort, aber es ist aktiv schädlich für Ihre Sicherheit. Sie sollten die fehlende Zertifizierungsstelle gemäß der Antwort von @ CoolAJ86 unten hinzufügen.
Mikemaccana
4
Ich verwende die NodeJS Plugin namens nodemailerund nodemailer-smtp-transportund der gleiche allgemeine Befehl gearbeitet. Sie müssen dies zu Ihrem createTransportObjekt hinzufügen :tls:{rejectUnauthorized: false}
LukeP
3
@LukeP genauso unsicher mit Nodemailer, denke ich. Es gibt einen Hinweis auf den Namen: wenn etwas von Un autorisiert, möchten Sie in der Regel , es abzulehnen, per Definition. Sie müssen einen Weg finden, um es korrekt zu autorisieren (indem Sie CA-Zertifikate ordnungsgemäß einrichten, wie andere Antworten bereits gesagt haben).
Bruno
@Bruno Ich stimme zu, Sie sollten es mit Zertifikaten richtig einrichten. Ich wollte lediglich einen Schnelltest für eine Demo einrichten, damit der von mir veröffentlichte Code eine schnelle Lösung darstellt. Ich hätte das in meinem Kommentar vorwegnehmen sollen.
LukeP
1
@mikemaccana Es gibt kein Sicherheitsproblem, wenn sich die Anforderung auf demselben Server befindet und Sie der einzige Eigentümer sind.
Binar Web
89

Es ist kein Problem mit der Anwendung, sondern mit dem Zertifikat, das von einer zwischengeschalteten Zertifizierungsstelle signiert ist. Wenn Sie diese Tatsache akzeptieren und dennoch fortfahren möchten, fügen Sie Folgendes hinzu, um Optionen anzufordern:

rejectUnauthorized: false

Vollständige Anfrage:

request({
    "rejectUnauthorized": false,
    "url": domain+"/api/orders/originator/"+id,
    "method": "GET",
    "headers":{
        "X-API-VERSION": 1,
        "X-API-KEY": key
    },
}, function(err, response, body){
    console.log(err);
    console.log(response);
    console.log(body);
});
Andrei Karpushonak
quelle
Ich habe dieses Problem gerade bei der Arbeit. Ich habe ein IT-Ticket eingereicht, das ihnen mitteilt, dass SSL möglicherweise falsch konfiguriert ist - sie sagten mir, ich sei verrückt. Gibt es weitere Informationen, die ich ihnen geben kann, um dieses Problem zu beheben?
Blakev
Dies ist eigentlich nicht korrekt: Wie CoolAJ86 und hectorcorrea erwähnen, ist das Zertifikat gültig, wird jedoch von einer zwischengeschalteten Zertifizierungsstelle signiert.
Mikemaccana
80

Die sichere Lösung

Anstatt die Sicherheit zu deaktivieren, können Sie der Kette die erforderlichen Zertifikate hinzufügen. Installieren Sie zuerst das ssl-root-cas- Paket von npm:

npm install ssl-root-cas

Dieses Paket enthält viele Zwischenzertifikate, denen Browser vertrauen, Knoten jedoch nicht.

var sslRootCAs = require('ssl-root-cas/latest')
sslRootCAs.inject()

Fügt die fehlenden Zertifikate hinzu. Weitere Informationen finden Sie hier:

https://git.coolaj86.com/coolaj86/ssl-root-cas.js

Siehe auch die nächste Antwort unten

coolaj86
quelle
2
Verwendet der HTTP-Client nicht den Zertifikatspeicher für vertrauenswürdige Stammzertifizierungsstellen von Windows?
Richard Collette
1
Der Knoten verwendet die in der Binärdatei gebündelten Mozilla-Zertifikate und überschreibt sie, wenn Sie Ihr eigenes caArray bereitstellen . Ich weiß nicht, ob das http-Modul auch auf die Betriebssystemkette abzielt. Curl unter OS X scheint jedoch nur die OS-Kette zu verwenden und keine manuell angegebenen Zertifikate zuzulassen.
coolaj86
Muss dies für jeden Prozess ausgeführt werden oder kann ich es einmal ausführen und meine Zertifikate global aktualisieren?
Joshua Snider
Die Zertifikate werden an möglicherweise zwei Stellen gespeichert: (1) in die binäre Datei node.js integriert (2) in den Keystore des Betriebssystems. Wenn Ihre Zertifikate veraltet sind, müssen Sie dies in Ihren laufenden Code aufnehmen. Es ändert weder die Knotenbinärdatei noch Ihr Betriebssystem - nur den Projektordner.
coolaj86
1
@ Sunkas Es ist genau das, was die Fehlermeldungen sagen. Ich weiß nicht, wie ich es einfacher erklären soll. Es ist eine schreibgeschützte Datei und kann nicht bearbeitet werden.
coolaj86
45

Die Lösung von CoolAJ86 ist korrekt und beeinträchtigt Ihre Sicherheit nicht wie das Deaktivieren aller Überprüfungen mit rejectUnauthorizedoder NODE_TLS_REJECT_UNAUTHORIZED. Möglicherweise müssen Sie jedoch das Zertifikat einer zusätzlichen Zertifizierungsstelle explizit einfügen.

Ich habe zuerst die Root-CAs ausprobiert, die im ssl-root-cas- Modul enthalten sind:

require('ssl-root-cas/latest')
  .inject();

Ich bin immer noch mit dem UNABLE_TO_VERIFY_LEAF_SIGNATUREFehler gelandet. Dann fand ich heraus, wer das Zertifikat für die Website ausgestellt hat, zu der ich vom COMODO SSL Analyzer eine Verbindung hergestellt habe, lud das Zertifikat dieser Behörde herunter und versuchte, nur dieses hinzuzufügen:

require('ssl-root-cas/latest')
  .addFile(__dirname + '/comodohigh-assurancesecureserverca.crt');

Am Ende hatte ich einen weiteren Fehler : CERT_UNTRUSTED. Schließlich injizierte ich die zusätzlichen Stammzertifizierungsstellen und fügte "meine" (anscheinend zwischengeschaltete) Zertifizierungsstelle hinzu, was funktionierte:

require('ssl-root-cas/latest')
  .inject()
  .addFile(__dirname + '/comodohigh-assurancesecureserverca.crt');
Ferdinand Prantl
quelle
1
Ich habe eine Verbindung zu einer Website mit einem Zertifikat hergestellt, das von der COMODO High-Assurance Secure Server-Zertifizierungsstelle ausgestellt wurde. Ich habe das Zertifikat von der Downloadseite heruntergeladen .
Ferdinand Prantl
2
Danke dir! Für mein Problem musste ich die gesamte Kette von Zertifikaten hinzufügen, um diesen Fehler zu überwinden. Für andere Referenz, zeigte dieser Beitrag mir , wie leicht die benötigten pem Dateien über Firefox exportieren: superuser.com/a/97203
mfink
Na danke für die Hilfe. In meinem Fall war es am Ende eine schlechte Konfiguration des SSL-Servers, nicht des Knotens. Nicht alle Zwischenzertifikate wurden auf dem Server installiert.
Scott Jungwirth
Wenn Sie das Zertifikat als .cerLauf erhalten openssl x509 -inform DER -in YOUR_CERTIFICATE.cer -out YOUR_CERTIFICATE.crt, konvertieren Sie es .crtvorher
0x1gene
8

Für Create React App (wo dieser Fehler ebenfalls auftritt und diese Frage das erste Google-Ergebnis ist) verwenden Sie wahrscheinlich HTTPS=true npm startein proxy(in package.json), das zu einer HTTPS-API führt, die selbst in der Entwicklung selbst signiert ist.

Wenn dies der Fall ist, sollten Sie Folgendes ändern proxy:

"proxy": {
  "/api": {
    "target": "https://localhost:5001",
    "secure": false
  }
}

secure entscheidet, ob der WebPack-Proxy die Zertifikatkette überprüft oder nicht, und durch Deaktivieren wird sichergestellt, dass das selbstsignierte API-Zertifikat nicht überprüft wird, damit Sie Ihre Daten erhalten.

Tomáš Hübelbauer
quelle
4

Es kann sehr verlockend sein, es zu tun rejectUnauthorized: falseoder process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';aber nicht zu tun! Es setzt Sie Menschen in den mittleren Angriffen aus.

Die anderen Antworten sind insofern richtig, als das Problem in der Tatsache liegt, dass Ihr Zertifikat "von einer zwischengeschalteten Zertifizierungsstelle signiert" ist. Hierfür gibt es eine einfache Lösung, für die keine Bibliothek eines Drittanbieters wie das ssl-root-casEinfügen zusätzlicher CAs in den Knoten erforderlich ist .

Die meisten https-Clients in Knoten unterstützen Optionen, mit denen Sie pro Anforderung eine Zertifizierungsstelle angeben können, die aufgelöst wird UNABLE_TO_VERIFY_LEAF_SIGNATURE. Hier ist ein einfaches Beispiel mit dem integrierten httpsModul des Knotens .

import https from 'https';

const options = {
  host: '<your host>',
  defaultPort: 443,
  path: '<your path>',
  // assuming the bundle file is co-located with this file
  ca: readFileSync(__dirname + '/<your bundle file>.ca-bundle'),
  headers: {
    'content-type': 'application/json',
  }
};
https.get(options, res => {
  // do whatever you need to do
})

Wenn Sie jedoch die SSL-Einstellungen auf Ihrem Hosting-Server konfigurieren können, besteht die beste Lösung darin, die Zwischenzertifikate Ihrem Hosting-Anbieter hinzuzufügen. Auf diese Weise muss der Client-Anforderer keine Zertifizierungsstelle angeben, da diese im Server selbst enthalten ist. Ich persönlich benutze namecheap + heroku. Der Trick für mich war, eine CRT-Datei mit zu erstellen cat yourcertificate.crt bundle.ca-bundle > server.crt. Ich habe diese Datei dann geöffnet und nach dem ersten Zertifikat eine neue Zeile hinzugefügt. Sie können mehr unter lesen

https://www.namecheap.com/support/knowledgebase/article.aspx/10050/33/installing-an-ssl-certificate-on-heroku-ssl

Simon
quelle
Dieser Fehler tritt hauptsächlich in der lokalen Umgebung auf, nicht in der Produktion. Wenn Sie also in der lokalen Umgebung sind, ist dies in Ordnung: process.env ['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
Vivex
@Vivex - Es ist nicht in Ordnung, dies in einer lokalen Umgebung zu tun, wenn der springende Punkt darin besteht, zu testen, wie Ihre SSL-Zertifikate funktionieren und wie sie weitergegeben werden ...
dwanderson
2

Nur hier für den Fall, dass es jemandem hilft, mein Fall war anders und ein bisschen seltsam. Ich erhielt dies auf eine Anfrage, auf die über Superagent zugegriffen wurde - das Problem hatte nichts mit Zertifikaten zu tun (die ordnungsgemäß eingerichtet wurden) und alles damit, dass ich das Superagent-Ergebnis dann über den Wasserfall-Rückruf des Async- Moduls weiterleitete. So beheben Sie das Problem: Anstatt das gesamte Ergebnis zu übergeben, result.bodydurchlaufen Sie einfach den Rückruf des Wasserfalls.

k00k
quelle
2

Ich hatte die gleichen Probleme. Ich habe die Lösungen @ThomasReggi und @ CoolAJ86 befolgt und gut gearbeitet, bin aber mit der Lösung nicht zufrieden.

Da das Problem "UNABLE_TO_VERIFY_LEAF_SIGNATURE" aufgrund der Konfigurationsstufe der Zertifizierung aufgetreten ist.

Ich nehme @thirdender Lösung , aber seinen Teil solution.As pro der nginx offiziellen Website, sie klar genanntes Zertifikat soll Kombination des Server - Zertifikats und verketteten Zertifikate sein.

Geben Sie hier die Bildbeschreibung ein

Sharathi RB
quelle
1

Sie können auch durch das Setzen versuchen strictSSL zu false, wie folgt aus :

{  
   url: "https://...",
   method: "POST",
   headers: {
        "Content-Type": "application/json"},
   strictSSL: false
}
SUBHAJIT GANGULI
quelle
0

Ich hatte ein Problem mit meiner Apache-Konfiguration, nachdem ich ein GoDaddy-Zertifikat in einer Subdomain installiert hatte. Ich dachte ursprünglich, es könnte ein Problem sein, wenn Node keinen Server Name Indicator (SNI) sendet, aber das war nicht der Fall. Das Analysieren des SSL-Zertifikats der Subdomain mit https://www.ssllabs.com/ssltest/ ergab den Fehler. Kettenprobleme: Unvollständig .

Nach dem Hinzufügen der von GoDaddy bereitgestellten gd_bundle-g2-g1.crtDatei über die SSLCertificateChainFileApache-Direktive konnte Node eine Verbindung über HTTPS herstellen, und der Fehler wurde behoben.

Thirdender
quelle
0

Sie müssen das Zwischenzertifikat in Ihren Server aufnehmen. Dies löst den [Fehler: UNABLE_TO_VERIFY_LEAF_SIGNATURE]


quelle
0

Ein anderer Ansatz zur sicheren Lösung besteht darin, das folgende Modul zu verwenden.

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
0

Wenn Sie zu diesem Thread kommen, weil Sie das Modul postgres / pg des Knotens verwenden, gibt es eine bessere Lösung als das Festlegen von NODE_TLS_REJECT_UNAUTHORIZEDoder rejectUnauthorized, was zu unsicheren Verbindungen führt.

Konfigurieren Sie stattdessen die Option "ssl" so, dass sie mit den Parametern für tls.connect übereinstimmt :

{
  ca: fs.readFileSync('/path/to/server-ca.pem').toString(),
  cert: fs.readFileSync('/path/to/client-cert.pem').toString(),
  key: fs.readFileSync('/path/to/client-key.pem').toString(),
  servername: 'my-server-name' // e.g. my-project-id/my-sql-instance-id for Google SQL
}

Ich habe ein Modul Hilfe geschrieben mit wie diese Optionen von Umgebungsvariablen Parsen PGSSLROOTCERT, PGSSLCERTund PGSSLKEY:

https://github.com/programmarchy/pg-ssl

Donald
quelle
0

Folgende Befehle haben bei mir funktioniert:

> npm config set strict-ssl false
> npm cache clean --force

Das Problem besteht darin, dass Sie versuchen, ein Modul aus einem Repository mit einem fehlerhaften oder nicht vertrauenswürdigen SSL-Zertifikat (Secure Sockets Layer) zu installieren. Sobald Sie den Cache bereinigt haben, ist dieses Problem behoben. Möglicherweise müssen Sie ihn später auf true setzen.

Shagun Pruthi
quelle