Không thể xác minh chữ ký lá


142

Tôi đang sử dụng node.js request.js để tiếp cận api. Tôi đang gặp lỗi này

[Lỗi: UNABLE_TO_VERIFY_LEAF_SIGNATURE]

Tất cả thông tin đăng nhập của tôi đều chính xác và hợp lệ và máy chủ vẫn ổn. Tôi đã thực hiện cùng một yêu cầu với người đưa thư.

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

Mã này chỉ đang chạy trong một tập lệnh thực thi cũ. node ./run_file.js, Có phải đó là lý do? Có cần phải chạy trên một máy chủ?


Đây là một cú sút xa, nhưng có thể là API không nhận ra tác nhân người dùng đang được chương trình nút của bạn chuyển qua?
Hector Correa


@HectorCorrea Tôi đã có thể đọc api trong postman một cách hoàn hảo. Tại sao nút không thể làm điều đó? Tôi đã thử thay đổi tác nhân người dùng, không có may mắn.
ThomasReggi

Câu trả lời:


157

Lưu ý : những điều sau đây là nguy hiểm và sẽ cho phép nội dung API bị chặn và sửa đổi giữa máy khách và máy chủ.

Điều này cũng làm việc

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


22
Tôi đã sửa chữa điều này và cảm ơn vì đã trả lời, nhưng nó chủ động gây hại cho an ninh của bạn. Bạn nên thêm câu trả lời CA thiếu trên mỗi câu trả lời của @ CoolAJ86 bên dưới.
mikemaccana

4
Tôi đang sử dụng plugin NodeJS được gọi nodemailernodemailer-smtp-transportcùng một lệnh chung đã hoạt động. Bạn cần thêm phần này vào createTransportđối tượng của mình :tls:{rejectUnauthorized: false}
LukeP

3
Tôi đoán là @LukeP không an toàn với cái gật đầu. Có một đầu mối trong tên: nếu một cái gì đó của Un được ủy quyền, bạn thường muốn từ chối nó, theo định nghĩa. Những gì bạn cần là tìm cách cho phép chính xác (bằng cách thiết lập chứng chỉ CA đúng cách, như các câu trả lời khác đã nói).
Bruno

@Bruno Tôi đồng ý, bạn nên thiết lập nó đúng cách với chứng chỉ. Tôi chỉ muốn thiết lập một thử nghiệm nhanh cho bản demo để mã tôi đã đăng là một bản sửa lỗi nhanh. Tôi nên đã mở đầu với điều đó trong bình luận của tôi.
LukeP

1
@mikemaccana Không có vấn đề bảo mật nếu yêu cầu nằm trên cùng một máy chủ và bạn là chủ sở hữu duy nhất.
Binar Web

89

Đây không phải là vấn đề với ứng dụng, nhưng với chứng chỉ được ký bởi CA trung gian. Nếu bạn chấp nhận thực tế đó và vẫn muốn tiếp tục, hãy thêm các tùy chọn sau vào yêu cầu:

rejectUnauthorized: false

Yêu cầu đầy đủ:

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

Tôi có vấn đề này ngay bây giờ tại nơi làm việc. Tôi đã gửi một vé CNTT cho họ biết SSL có thể bị định cấu hình sai - họ nói với tôi rằng tôi là craZY. Có thêm thông tin nào tôi có thể cung cấp cho họ để giải quyết vấn đề này không?
blakev

Điều này thực sự không đúng: như CoolAJ86 và hectorcorrea đề cập, chứng chỉ hợp lệ, nhưng nó được ký bởi một trung gian CA.
mikemaccana

80

Giải pháp an toàn

Thay vì tắt bảo mật, bạn có thể thêm các chứng chỉ cần thiết vào chuỗi. Lần đầu tiên cài đặt gói ssl-root-cas từ npm:

npm install ssl-root-cas

Gói này chứa nhiều chứng chỉ trung gian mà trình duyệt tin tưởng nhưng nút thì không.

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

Sẽ thêm các chứng chỉ còn thiếu. Xem ở đây để biết thêm:

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

Ngoài ra, xem câu trả lời tiếp theo dưới đây


2
Có phải máy khách http không sử dụng kho lưu trữ chứng chỉ Windows Trusted Root Certified Authorities không?
Richard Collette

1
nút sử dụng các cerz mozilla được gói trong nhị phân và nó ghi đè lên chúng bất cứ khi nào bạn cung cấp camảng của riêng bạn . Tôi không biết nếu mô-đun http của nó cũng sẽ tìm đến chuỗi hệ điều hành. Tuy nhiên, curl trên OS X dường như chỉ sử dụng chuỗi OS và không cho phép các certs được chỉ định thủ công.
coolaj86

Điều này có phải được chạy cho mỗi quy trình hay tôi có thể chạy nó một lần và cập nhật chứng chỉ của mình trên toàn cầu?
Joshua Snider

Các chứng chỉ được lưu trữ ở hai vị trí tiềm năng: (1) tích hợp vào tệp nhị phân node.js (2) kho khóa của hệ điều hành. Nếu certs của bạn đã hết hạn, bạn sẽ cần phải bao gồm điều này trong mã đang chạy của bạn. Nó không thay đổi nhị phân nút cũng như hệ điều hành của bạn - chỉ thư mục dự án.
coolaj86

1
@Sunkas Đó chính xác là những gì các thông báo lỗi nói. Tôi không biết làm thế nào để giải thích nó đơn giản hơn. Đây là một tệp chỉ đọc và không thể chỉnh sửa.
coolaj86

45

Giải pháp của CoolAJ86 là chính xác và nó không ảnh hưởng đến bảo mật của bạn như vô hiệu hóa tất cả các kiểm tra bằng cách sử dụng rejectUnauthorizedhoặc NODE_TLS_REJECT_UNAUTHORIZED. Tuy nhiên, bạn có thể cần phải tiêm chứng chỉ CA bổ sung một cách rõ ràng.

Trước tiên tôi đã thử các CA gốc được bao gồm bởi mô đun ssl-root-cas :

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

Tôi vẫn kết thúc với UNABLE_TO_VERIFY_LEAF_SIGNATURElỗi. Sau đó, tôi phát hiện ra ai đã cấp chứng chỉ cho trang web mà tôi đang kết nối với Trình phân tích SSL COMODO , đã tải xuống chứng chỉ của cơ quan đó và chỉ cố gắng thêm chứng chỉ đó:

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

Tôi đã kết thúc với một lỗi khác : CERT_UNTRUSTED. Cuối cùng, tôi đã tiêm các CA gốc bổ sung và bao gồm CA "của tôi" (dường như là trung gian), hoạt động:

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

1
Tôi đã kết nối với một trang web với chứng nhận được cấp bởi Máy chủ bảo mật an toàn bảo đảm cao COMODO. Tôi đã tải chứng chỉ từ trang tải xuống của họ .
Ferdinand Prantl

2
Cảm ơn bạn! Đối với vấn đề của tôi, tôi cần thêm toàn bộ chuỗi certs để vượt qua lỗi này. Đối với những người khác tham khảo, bài đăng này chỉ cho tôi cách dễ dàng xuất các tệp pem cần thiết thông qua Firefox: superuser.com/a/97203
mfink

Vâng cảm ơn sự giúp đỡ. Trong trường hợp của tôi, cuối cùng thì đó là một cấu hình xấu của máy chủ SSL, không phải nút. Không phải tất cả các certs trung gian đã được cài đặt trên máy chủ.
Scott Jungwirth

nếu bạn nhận được chứng chỉ dưới dạng .cerchạy này openssl x509 -inform DER -in YOUR_CERTIFICATE.cer -out YOUR_CERTIFICATE.crtđể chuyển đổi nó .crttrước
0x1gene

8

Đối với Ứng dụng Tạo phản ứng (cũng xảy ra lỗi này và câu hỏi này là kết quả số 1 của Google), có lẽ bạn đang sử dụng HTTPS=true npm startproxy(trong package.json) đi đến một số API HTTPS tự phát hành khi được phát triển.

Nếu đó là trường hợp, hãy xem xét thay đổi proxynhư thế này:

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

secure quyết định xem proxy WebPack có kiểm tra chuỗi chứng chỉ hay không và vô hiệu hóa để đảm bảo chứng chỉ tự ký API không được xác minh để bạn có được dữ liệu của mình.


4

Nó có thể rất hấp dẫn để làm rejectUnauthorized: falsehoặc process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';nhưng đừng làm điều đó! Nó phơi bày bạn với người đàn ông trong các cuộc tấn công giữa.

Các câu trả lời khác đều đúng ở chỗ vấn đề nằm ở chỗ chứng chỉ của bạn "được ký bởi một CA trung gian". Có một giải pháp dễ dàng cho vấn đề này, một giải pháp không yêu cầu thư viện bên thứ ba như ssl-root-cashoặc tiêm thêm bất kỳ CA nào vào nút.

Hầu hết các máy khách https trong các tùy chọn hỗ trợ nút cho phép bạn chỉ định CA theo yêu cầu, sẽ giải quyết UNABLE_TO_VERIFY_LEAF_SIGNATURE. Đây là một ví dụ đơn giản sử dụng httpsmô đun int-int của nút .

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

Tuy nhiên, nếu bạn có thể định cấu hình cài đặt ssl trong máy chủ lưu trữ của mình, giải pháp tốt nhất sẽ là thêm chứng chỉ trung gian cho nhà cung cấp dịch vụ lưu trữ của bạn. Bằng cách đó, người yêu cầu khách hàng không cần chỉ định CA, vì nó được bao gồm trong chính máy chủ. Cá nhân tôi sử dụng namecheap + heroku. Mẹo cho tôi là tạo một tệp .crt với cat yourcertificate.crt bundle.ca-bundle > server.crt. Sau đó tôi đã mở tập tin này và thêm một dòng mới sau chứng chỉ đầu tiên. Bạn có thể đọc thêm tại

https://www.namecheap.com/support/ledgeledridease/article.aspx/10050/33/installing-an-ssl-cert ve-on-heroku-ssl


Lỗi này chủ yếu xuất hiện trong môi trường cục bộ, không phải trong sản xuất, vì vậy nếu bạn ở địa phương thì sẽ ổn: process.env ['NODE_TLS_RE DỰ_UNAUTHORIZED'] = '0';
Vivex

@Vivex - không ổn khi làm điều đó trong môi trường địa phương nếu toàn bộ vấn đề là kiểm tra cách thức hoạt động của SSL SSL và cách chúng được thông qua ...
dwanderson

2

Chỉ cần đặt điều này ở đây trong trường hợp nó giúp được ai đó, trường hợp của tôi đã khác và một chút pha trộn kỳ lạ. Tôi đã nhận được điều này theo yêu cầu được truy cập thông qua superagent - vấn đề không liên quan gì đến chứng chỉ (được thiết lập đúng) và tất cả đều liên quan đến thực tế là sau đó tôi đã chuyển kết quả siêu tốc qua cuộc gọi lại thác nước của mô-đun async . Để khắc phục: Thay vì chuyển toàn bộ kết quả, chỉ cần chuyển result.bodyqua cuộc gọi lại của thác nước.


2

Tôi đã có những vấn đề tương tự. Tôi đã theo dõi giải pháp @ThomasReggi và @ CoolAJ86 và hoạt động tốt nhưng tôi không hài lòng với giải pháp đó.

Bởi vì sự cố "UNABLE_TO_VERIFY_LEAF_SIGNATURE" xảy ra do mức cấu hình chứng nhận.

Tôi chấp nhận giải pháp @thirdender nhưng là giải pháp một phần. Trên trang web chính thức của nginx , họ đề cập rõ ràng chứng chỉ nên được kết hợp giữa Chứng chỉ máy chủ và chứng chỉ xích.

nhập mô tả hình ảnh ở đây


1

Bạn cũng có thể thử bằng cách đặtrictSSL thành false, như thế này:

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

0

Tôi gặp vấn đề với cấu hình Apache của mình sau khi cài đặt chứng chỉ GoDaddy trên tên miền phụ. Ban đầu tôi nghĩ đó có thể là một vấn đề với Node không gửi Chỉ báo tên máy chủ (SNI), nhưng đó không phải là vấn đề. Phân tích chứng chỉ SSL của tên miền phụ với https://www.ssllabs.com/ssltest/ đã trả về lỗi Sự cố chuỗi: Chưa hoàn tất .

Sau khi thêm gd_bundle-g2-g1.crttệp được cung cấp GoDaddy thông qua SSLCertificateChainFilechỉ thị Apache, Node đã có thể kết nối qua HTTPS và lỗi đã biến mất.


0

Bạn phải bao gồm chứng chỉ Trung cấp trong máy chủ của bạn. Điều này giải quyết [Lỗi: UNABLE_TO_VERIFY_LEAF_SIGNATURE]


0

Một cách tiếp cận khác để giải quyết vấn đề này một cách an toàn là sử dụng mô-đun sau.

node_extra_ca_certs_mozilla_bundle

Mô-đun này có thể hoạt động mà không cần sửa đổi mã bằng cách tạo tệp PEM bao gồm tất cả các chứng chỉ gốc và trung gian được Mozilla tin cậy. Bạn có thể sử dụng biến môi trường sau (Hoạt động với Nodejs v7.3 +),

NODE_EXTRA_CA_CERTS

Để tạo tệp PEM để sử dụng với biến môi trường trên. Bạn có thể cài đặt mô-đun bằng cách sử dụng:

npm install --save node_extra_ca_certs_mozilla_bundle

và sau đó khởi chạy tập lệnh nút của bạn với một biến môi trường.

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

Các cách khác để sử dụng tệp PEM được tạo có sẵn tại:

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

LƯU Ý: Tôi là tác giả của mô-đun trên.


0

Nếu bạn đến với chủ đề này bởi vì bạn đang sử dụng mô-đun postgres / pg nút, có một giải pháp tốt hơn là cài đặt NODE_TLS_REJECT_UNAUTHORIZEDhoặc rejectUnauthorized, điều này sẽ dẫn đến các kết nối không an toàn.

Thay vào đó, hãy định cấu hình tùy chọn "ssl" để khớp với các tham số cho tls.connect :

{
  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
}

Tôi đã viết một module để giúp đỡ với phân tích các tùy chọn từ biến môi trường như PGSSLROOTCERT, PGSSLCERTPGSSLKEY:

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


0

Các lệnh sau làm việc cho tôi:

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

Vấn đề là bạn đang cố gắng cài đặt một mô-đun từ kho lưu trữ với chứng chỉ SSL [Lớp cổng bảo mật] xấu hoặc không đáng tin cậy. Khi bạn xóa bộ nhớ cache, vấn đề này sẽ được giải quyết. Bạn có thể cần phải chuyển nó thành đúng sau này.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.