Kesalahan: tidak dapat memverifikasi sertifikat pertama di nodejs

141

Saya mencoba mengunduh file dari server jira menggunakan url tapi saya mendapat kesalahan. cara memasukkan sertifikat ke dalam kode untuk memverifikasi Kesalahan:

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)

Kode Nodejs saya:

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
sumber
apakah Anda bisa menyelesaikan ini?
sharad jain
1
saya menggunakan prosedur lain seperti menonaktifkan verifikasi sertifikat dan selesai
Labeo
dapatkah Anda menjelaskan lebih banyak? Ini akan sangat membantu saya
sharad jain
lihat jawaban di bawah untuk validasi sertifikat yang harus kami tolak tanpa otorisasi
Labeo

Jawaban:

120

Coba tambahkan sertifikat root yang sesuai

Ini akan selalu menjadi pilihan yang jauh lebih aman daripada hanya menerima secara buta poin akhir yang tidak sah, yang pada gilirannya hanya akan digunakan sebagai upaya terakhir.

Ini bisa sesederhana menambahkan

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

ke aplikasi Anda.

The SSL Akar CA paket NPM (seperti yang digunakan di sini) adalah paket yang sangat berguna mengenai masalah ini.

Joshua
sumber
9
Jawaban ini harus digunakan dalam banyak kasus karena ini benar-benar memperbaiki masalah daripada menonaktifkan seluruh manfaat SSL.
mikemaccana
12
Seperti yang dinyatakan dalam modul ssl-root-cas README, salah satu penyebab paling umum untuk masalah ini adalah bahwa sertifikat Anda tidak menyematkan sertifikat CA menengahnya. Coba perbaiki sertifikat Anda sebelum mencoba yang lain;)
Laurent VB
Anda bahkan mungkin tidak memerlukan paket SSL-root-cas. Cukup atur globalAgents.option.cert ke sertifikat rantai penuh. Itulah yang memecahkan masalah saya.
smartexpert
1
mkcert tidak membuat sertifikat "rantai penuh". Anda harus menyatukan sertifikat Anda dengan sertifikat root yang tersedia di $(mkcert -CAROOT)/rootCA.pemdalam file sertifikat baru dan melakukan sesuatu seperti https.globalAgent.options.ca = fs.readFileSync('fullchain.pem')Lihat github.com/FiloSottile/mkcert/issues/76
Frosty Z
Untuk keamanan, ssl-root-casmodul npm memiliki permintaan ke mozilla.org hardcoded git.coolaj86.com/coolaj86/ssl-root-cas.js/src/branch/master/… . Mungkin aman karena Mozilla tetapi sepertinya vektor serangan.
Avindra Goolcharan
60

Peretasan kotor lainnya, yang akan membuat semua permintaan Anda tidak aman:

process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0
Satara
sumber
8
Ini sepertinya tidak berbeda dengan jawaban Labeo di atas , sama berbahayanya.
ocramot
4
Berbeda, tidak memerlukan perubahan kode karena variabel env dapat diatur di luar kode sumber.
jzacharuk
1
Jawaban ini berbahaya. Anda menonaktifkan keamanan yang disediakan TLS.
Flimm
1
Ini bekerja untuk saya, sangat membantu. Dalam kasus saya, saya hanya berbicara dengan localhost , jadi keamanan bukan masalah.
Mike S
Baik memang hanya untuk menguji localhost. Pastikan Anda menghapusnya setelah pengujian.
Nico
44

diperlukan untuk tidak dapat memverifikasi sertifikat pertama di nodejs menolak diperlukan tidak sah

 request({method: "GET", 
        "rejectUnauthorized": false, 
        "url": url,
        "headers" : {"Content-Type": "application/json",
        function(err,data,body) {
    }).pipe(
       fs.createWriteStream('file.html'));
Labeo
sumber
129
Jawaban ini berbahaya. Yang lainnya lebih aman.
mikemaccana
3
Nah dengan melakukan itu, Anda menghapus keamanan yang disediakan oleh SSL, sehingga harus digunakan untuk pengembangan saja.
Sylvain
11
Tidak memeriksa sertifikat berarti bahwa Anda tidak dapat memastikan identitas pihak lain dan karenanya mungkin tunduk pada host palsu. Meskipun Anda tidak memeriksa sertifikat, Anda tetap mendapatkan komunikasi terenkripsi yang tidak dapat (dengan mudah) dimata-matai. Jadi menambahkan baris ini tidak "menghapus keamanan" dari SSL juga, seperti komentator lain mengatakan "nonaktifkan seluruh manfaat SSL".
Bob Pollack
4
Menonaktifkan verifikasi SSL BUKAN solusi untuk masalah apa pun. :-)
Siddhu
9
Ini berfungsi jika Anda menggunakan pustaka permintaan simpul. Saya ini. Dan terima kasih, ini memecahkan kebutuhan saya yang mendesak untuk pengembangan.
Alan
29

Server yang Anda coba unduh mungkin terkonfigurasi dengan buruk. Bahkan jika itu bekerja di browser Anda, itu mungkin tidak termasuk semua sertifikat publik dalam rantai yang diperlukan untuk klien yang mengosongkan cache untuk memverifikasi.

Saya sarankan memeriksa situs di alat SSLlabs: https://www.ssllabs.com/ssltest/

Cari kesalahan ini:

Rantai sertifikat server ini tidak lengkap.

Dan ini:

Masalah rantai ......... Tidak lengkap

Flimm
sumber
Saya mendapatkan masalah ini (Masalah rantai ......... Tidak lengkap) untuk sertifikat saya yang diotorisasi dari DigiCert Inc., bagaimana prosedur untuk memperbaikinya?
imarchuang
@imarchuang Singkatnya, server Anda perlu melayani tidak hanya sertifikat untuk domain Anda, tetapi juga sertifikat perantara. Saya tidak dapat memasukkan lebih detail dalam komentar ini, tetapi mudah-mudahan itu informasi yang cukup untuk mengarahkan Anda ke arah yang benar.
Flimm
terima kasih banyak, kami menemukan
jawabannya
Terimakasih! Saya menemukan sertifikat saya tidak lengkap, meskipun bekerja dengan sempurna di chrome dan firefox tetapi tidak bekerja di aplikasi elektron, dan saya memperbaikinya di sisi nginx olehcat domainname.crt domainname.ca-bundle > domainname-ssl-bundle.crt
Ivan Borshchov
26

unable to verify the first certificate

Rantai sertifikat tidak lengkap.

Ini berarti bahwa server web yang Anda sambungkan salah konfigurasi dan tidak menyertakan sertifikat perantara dalam rantai sertifikat yang dikirimkan kepada Anda.

Rantai sertifikat

Kemungkinan besar terlihat sebagai berikut:

  1. Sertifikat server - menyimpan sertifikat yang ditandatangani oleh perantara.
  2. Sertifikat perantara - menyimpan sertifikat yang ditandatangani oleh root.
  3. Sertifikat root - menyimpan sertifikat yang ditandatangani sendiri.

Sertifikat perantara harus dipasang di server, bersama dengan sertifikat server.
Sertifikat root disematkan ke aplikasi perangkat lunak, browser, dan sistem operasi.

Aplikasi yang melayani sertifikat harus mengirim rantai lengkap, ini berarti sertifikat server itu sendiri dan semua perantara. Sertifikat root seharusnya diketahui oleh klien.

Buat kembali masalahnya

Pergi ke https://incomplete-chain.badssl.com menggunakan browser Anda.

Itu tidak menunjukkan kesalahan apa pun (gembok di bilah alamat berwarna hijau).
Itu karena browser cenderung menyelesaikan rantai jika tidak dikirim dari server.

Sekarang, terhubung ke https://incomplete-chain.badssl.com menggunakan Node:

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

Log: " Kesalahan: tidak dapat memverifikasi sertifikat pertama ".

Larutan

Anda harus menyelesaikan sendiri rantai sertifikat.

Untuk melakukannya:

1: Anda harus mendapatkan sertifikat perantara yang hilang dalam .pemformat

2a: memperpanjang toko sertifikat built-in Node menggunakan NODE_EXTRA_CA_CERTS,

2b: atau lulus bundel sertifikat Anda sendiri (perantara dan root) menggunakan caopsi.

1. Bagaimana cara saya mendapatkan sertifikat perantara?

Menggunakan openssl(dilengkapi dengan Git untuk Windows ).

Simpan detail sertifikat server jarak jauh:

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

Kami sedang mencari penerbit (sertifikat perantara adalah penerbit / penandatangan sertifikat server):

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

Itu harus memberi Anda URI sertifikat penandatanganan. Unduh itu:

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

Akhirnya, ubah menjadi .pem:

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

2a. NODE_EXTRA_CERTS

Saya menggunakan cross-env untuk mengatur variabel lingkungan dalam package.jsonfile:

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

2b. capilihan

Opsi ini akan menimpa CA root bawaan Node.

Itu sebabnya kita perlu membuat root CA kita sendiri. Gunakan ssl-root-cas .

Lalu, buat httpsagen khusus yang dikonfigurasi dengan bundel sertifikat kami (root dan perantara). Lewati agen ini axiosketika mengajukan permintaan.

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

Alih-alih membuat httpsagen khusus dan meneruskannya axios, Anda dapat menempatkan sertifikat pada httpsagen global:

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

Sumber:

  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. Cara mengonversi .crt ke .pem
sch
sumber
Penjelasan yang sangat rinci.
Tujuh
Benar benar menakjubkan! Tidak bekerja untuk saya, tetapi detail apa!
Tom Chadaravicius
6

Ini sebenarnya memecahkannya untuk saya, dari 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
sumber
1
Itu adalah solusi terbaik, karena tidak memerlukan perpustakaan tambahan dan sederhana
Martin Schneider
4

Anda mungkin dapat melakukan ini dengan mengubah opsi permintaan seperti di bawah ini. Jika Anda menggunakan sertifikat yang ditandatangani sendiri atau perantara yang hilang, menetapkan strictSSL ke false tidak akan memaksa paket permintaan untuk memvalidasi sertifikat.

var options = {
   host: 'jira.example.com',
   path: '/secure/attachment/206906/update.xlsx',
   strictSSL: false
}
Sundar
sumber
Ini menyelesaikan masalah saya, saya menggunakan modul 'permintaan' alih-alih 'http'. Terima kasih!
Bruno Nunes
2

GoDaddy SSL CCertificate

Saya pernah mengalami ini ketika mencoba terhubung ke server API backend kami dengan sertifikat GoDaddy dan di sini adalah kode yang saya gunakan untuk menyelesaikan masalah.

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:

Gunakan sertifikat yang dibundel dan jangan lupa untuk menginstal perpustakaan npm install ssl-root-cas

Dekan Christian Armada
sumber
1
ini bekerja untuk saya kecuali ketika mengimpor saya harus menggunakan "ssl-root-cas" bukan "ssl-root-cas / latest".
Krishnan
2

Ini Berfungsi Bagi Saya => menambahkan agen dan 'rejectUnauthorized' disetel ke false

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
sumber
1

Pendekatan lain untuk menyelesaikan ini adalah dengan menggunakan modul berikut.

node_extra_ca_certs_mozilla_bundle

Modul ini dapat bekerja tanpa modifikasi kode dengan membuat file PEM yang mencakup semua sertifikat root dan perantara yang dipercaya oleh Mozilla. Anda dapat menggunakan variabel lingkungan berikut (Bekerja dengan Nodejs v7.3 +),

NODE_EXTRA_CA_CERTS

Untuk menghasilkan file PEM untuk digunakan dengan variabel lingkungan di atas. Anda dapat menginstal modul menggunakan:

npm install --save node_extra_ca_certs_mozilla_bundle

dan kemudian meluncurkan skrip simpul Anda dengan variabel lingkungan.

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

Cara lain untuk menggunakan file PEM yang dihasilkan tersedia di:

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

CATATAN: Saya adalah penulis modul di atas.

arva
sumber
-3

Saya menggunakan modul NPM nodemailer. Kode di bawah ini menyelesaikan masalah

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