Помилка: не вдалося підтвердити перший сертифікат у nodejs


141

Я намагаюся завантажити файл з сервера jira за допомогою URL, але я отримую помилку. як включити сертифікат у код для підтвердження помилки:

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)

Мій код Nodejs:

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

    });
});

ти зміг це вирішити?
sharad jain

1
Я використав іншу процедуру, як відключення перевірки сертифікатів і виконаний
Labeo

Ви можете трохи більше розробити? Це буде дуже корисно для мене
sharad jain

дивіться нижче відповідь на підтвердження сертифікату, нам потрібно відхилитиУповноважений
Labeo

Відповіді:


120

Спробуйте додати відповідний кореневий сертифікат

Це завжди буде набагато безпечнішим варіантом, ніж просто сліпо прийняти несанкціоновані кінцеві точки, які в свою чергу повинні використовуватися лише в крайньому випадку.

Це може бути так само просто, як додавання

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

до вашої заявки.

Пакет npm SSL Root CAs (як тут використовується) є дуже корисним пакетом щодо цієї проблеми.


9
Цю відповідь слід використовувати в більшості випадків, оскільки вона фактично вирішує проблему, а не вимикає всю перевагу SSL.
mikemaccana

12
Як зазначено в модулі ssl-root-cas README, однією з найпоширеніших причин цієї проблеми є те, що ваш сертифікат не вставляє проміжні сертифікати CA. Спробуйте виправити свій сертифікат, перш ніж спробувати щось;)
Laurent VB

Можливо, вам навіть не знадобиться пакет SSL-root-cas. Просто встановіть globalAgents.option.cert на сертифікат fullchain. Ось це і вирішило мою проблему.
smartexpert

1
mkcert не створює сертифікат "fullchain". Ви повинні з'єднати свій сертифікат із кореневою скринькою, доступною $(mkcert -CAROOT)/rootCA.pemу новому файлі сертифікатів, і зробити щось на кшталт https.globalAgent.options.ca = fs.readFileSync('fullchain.pem')Див. Github.com/FiloSottile/mkcert/isissue/76
Frosty Z

Зважаючи на безпеку, ssl-root-casмодуль npm має запит на mozilla.org з жорстким кодом git.coolaj86.com/coolaj86/ssl-root-cas.js/src/branch/master/… . Це, мабуть, безпечно, оскільки Mozilla, але це здається вектором нападу.
Авіндра Гульчаран

60

Ще один брудний злом, який зробить усі ваші запити незахищеними:

process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0

8
Це здається не відрізняється від відповіді Лабео вище , так само небезпечно.
окламот

4
Це інакше, він не вимагає будь-яких змін кодування, оскільки змінну env можна встановити поза вихідним кодом.
jzacharuk

1
Ця відповідь небезпечна. Ви вимикаєте будь-яку безпеку, яку надає TLS.
Flimm

1
Це працювало для мене, супер корисно. У моєму випадку я просто розмовляю з localhost , тому безпека не є проблемою.
Майк S

Чудово дійсно просто перевірити localhost. Просто переконайтесь, що ви видалили його після тестів.
Ніко

44

для неможливості перевірити перший сертифікат у nodejs відхиленні потрібно неавторизовано

 request({method: "GET", 
        "rejectUnauthorized": false, 
        "url": url,
        "headers" : {"Content-Type": "application/json",
        function(err,data,body) {
    }).pipe(
       fs.createWriteStream('file.html'));

129
Ця відповідь небезпечна. Інший - безпечніший.
mikemaccana

3
Таким чином, ви видаляєте безпеку, надану SSL, тому його слід використовувати лише для розробки.
Sylvain

11
Якщо не перевіряти сертифікати, це означає, що ви не можете бути впевнені в особі іншої сторони, і тому ви можете бути підпорядкованим хостом. Навіть якщо ви не перевіряєте сертифікати, ви все одно отримуєте зашифроване повідомлення, яке неможливо (легко) підглядати. Таким чином, додавання цього рядка не "знімає безпеку" SSL і, як сказав інший коментатор, "відключає [] всю перевагу SSL".
Боб Поллак

4
Вимкнення перевірки SSL НЕ є вирішенням жодної проблеми. :-)
Siddhu

9
Це працює, якщо ви використовуєте бібліотеку запитів вузлів. Який я. І дякую, це вирішує мою негайну потребу в розвитку.
Алан

29

Сервер, з якого ви намагаєтеся завантажити, може бути неправильно налаштований. Навіть якщо він працює у вашому веб-переглядачі, він може не включати всі публічні сертифікати у ланцюжок, необхідний клієнтові-порожньому клієнту для підтвердження.

Рекомендую перевірити сайт в інструменті SSLlabs: https://www.ssllabs.com/ssltest/

Шукайте цю помилку:

Ланцюг сертифікатів цього сервера неповний.

І це:

Питання ланцюга ......... Неповне


Я отримую цю проблему (ланцюгові проблеми ......... неповна) для мого сертифіката, який має дозвіл від DigiCert Inc., яка процедура виправити це?
imarchuang

@imarchuang Коротше кажучи, ваш сервер повинен обслуговувати не лише сертифікат для вашого домену, але і проміжні сертифікати. Я не можу вмістити більш детальну інформацію в цьому коментарі, але, сподіваємось, це достатньо інформації, щоб направити вас у правильному напрямку.
Flimm

велике спасибі, ми розібралися, розчісуючи кореневу
череп

Дякую тобі! Я виявив, що мій серт був неповним, хоча він прекрасно працював у хромі та firefox, але не працював у додатку для електронних програм, і я виправив його з боку nginxcat domainname.crt domainname.ca-bundle > domainname-ssl-bundle.crt
Іван Борщов,

26

unable to verify the first certificate

Ланцюг сертифікатів неповний.

Це означає, що веб-сервер, до якого ви підключаєтесь, неправильно налаштований і не включив проміжний сертифікат у ланцюжок сертифікатів, який він надіслав вам.

Ланцюг сертифікатів

Це, швидше за все, виглядає так:

  1. Сертифікат сервера - зберігає сертифікат, підписаний проміжним.
  2. Проміжний сертифікат - зберігає сертифікат, підписаний коренем.
  3. Root сертифікат - зберігає самопідписаний сертифікат.

Проміжний сертифікат повинен бути встановлений на сервері разом із сервером.
Кореневі сертифікати вбудовані в програмні програми, браузери та операційні системи.

Додаток, що обслуговує сертифікат, повинен надіслати повний ланцюг, це означає сам сертифікат сервера та всі проміжні продукти. Корінний сертифікат повинен бути відомий клієнтом.

Відтворити проблему

Перейдіть на сторінку https://incomplete-chain.badssl.com за допомогою свого браузера.

Він не відображає помилок (замок в адресному рядку зелений).
Це тому, що браузери, як правило, завершують ланцюг, якщо він не надсилається з сервера.

Тепер підключіться до https://incomplete-chain.badssl.com за допомогою 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);
  });

Журнали: " Помилка: неможливо підтвердити перший сертифікат ".

Рішення

Потрібно самостійно заповнити ланцюжок сертифікатів.

Для цього:

1:.pem Тоді вам потрібно отримати пропущений проміжний сертифікат у форматі

2а: розширити вбудований сховище Node за допомогою NODE_EXTRA_CA_CERTS,

2b: або передайте власний пакет сертифікатів (проміжні та кореневі), використовуючи caопцію.

1. Як отримати проміжний сертифікат?

Використання openssl(поставляється з Git для Windows ).

Збережіть дані сертифікатів віддаленого сервера:

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

Ми шукаємо емітента (проміжний сертифікат - це емітент / підписант серверного сертифіката):

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

Він повинен дати вам URI сертифіката підписання. Завантажте його:

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

Нарешті, перетворіть його на .pem:

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

2а. NODE_EXTRA_CERTS

Я використовую крос-env для встановлення змінних середовища у package.jsonфайлі:

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

2б. caваріант

Ця опція буде замінена вбудованими кореневими ЦЗ у вузлі.

Ось чому нам потрібно створити власний корінь CA. Використовуйте ssl-root-cas .

Потім створіть спеціальний httpsагент, налаштований з нашим пакетом сертифікатів (кореневим та проміжним). Передайте цього агента, axiosколи ви робите запит.

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

Замість того, щоб створити спеціальний httpsагент і передати його axios, ви можете розмістити сертифікати на httpsглобальному агенті:

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

Ресурси:

  1. https://levelup.gitconnected.com/how-to-resolve-certificate-errors-in-nodejs-app-involving-ssl-calls-781ce48dadeded
  2. https://www.npmjs.com/package/ssl-root-cas
  3. https://github.com/nodejs/node/isissue/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. Як перетворити .crt в .pem

Дуже детальне пояснення.
Сім

Абсолютно дивовижно! Не працював для мене, але яка деталь!
Том Чадаравіцій

6

Це фактично вирішило це для мене, з 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
});

1
Це найкраще рішення, тому що воно не потребує додаткових бібліотек і просте
Мартін Шнайдер,

4

Ви можете зробити це, змінивши параметри запиту, як показано нижче. Якщо ви використовуєте самопідписаний сертифікат або відсутнього посередника, встановлення строки SSL на помилкове не змусить пакет запитів перевірити сертифікат.

var options = {
   host: 'jira.example.com',
   path: '/secure/attachment/206906/update.xlsx',
   strictSSL: false
}

Це вирішило мою проблему, я використовую модуль "запит" замість "http". Дякую!
Бруно Нунес

2

SSD сертифікат GoDaddy

Я відчував це під час спроби підключитися до нашого сервера API для сервера за допомогою сертифіката GoDaddy, і ось код, який я використав для вирішення проблеми

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:

Використовуйте пакетний сертифікат і не забудьте встановити бібліотеку npm install ssl-root-cas


1
це працювало для мене за винятком того, що під час імпорту мені довелося використовувати "ssl-root-cas" замість "ssl-root-cas / latest".
кришнан

2

Це працювало для мене => додавання агента та 'rejectUnauthorized' встановлено на 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;
    });
};


1

Інший підхід для вирішення цього питання полягає у використанні наступного модуля.

node_extra_ca_certs_mozilla_bundle

Цей модуль може працювати без будь-якої модифікації коду, генеруючи файл PEM, який включає всі кореневі та проміжні сертифікати, яким довіряє Mozilla. Ви можете використовувати таку змінну середовища (працює з Nodejs v7.3 +),

NODE_EXTRA_CA_CERTS

Для створення файлу PEM для використання з вищевказаною змінною середовища. Ви можете встановити модуль за допомогою:

npm install --save node_extra_ca_certs_mozilla_bundle

а потім запустіть сценарій вузла зі змінною середовища.

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

Інші способи використання створеного файлу PEM доступні за посиланням:

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

ПРИМІТКА: Я автор вищевказаного модуля.


-3

Я використовував nodemailer npm module. Нижче наведений код вирішив проблему

     tls: {
     // do not fail on invalid certs
     rejectUnauthorized: false
     }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.