Js 请求 CERT_HAS_EXPIRED

我使用 Mikeal 的请求(https://github.com/mikeal/request)向服务器发送 https 请求。但是,我不断收到 CERT _ HAS _ EXPIRED 的授权错误。

request({
url: 'https://www.domain.com/api/endpoint',
strictSSL: false
}, function(error, response, body) {
if(!error && response.statusCode == 200) {
res.json(JSON.parse(body));
} else {
res.json(response.statusCode, {'error': 'error'})
}
});

我尝试将 strictSSL 设置为 true 和 false,两者都输出 CERT _ HAS _ EXPIRED 相同的错误。是什么导致了这个问题,有没有办法在 nodejs 中修复它?

179463 次浏览

Add this at the top of your file:

process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';

DANGEROUS This disables HTTPS / SSL / TLS checking across your entire node.js environment. Please see the solution using an https agent below.

Try to temporarily modify request.js and harcode everywhere rejectUnauthorized = true, but it would be better to get the certificate extended as a long-term solution.

The best way to fix this:

Renew the certificate. This can be done for free using Greenlock which issues certificates via Let's Encrypt™ v2

A less insecure way to fix this:

'use strict';


var request = require('request');
var agentOptions;
var agent;


agentOptions = {
host: 'www.example.com'
, port: '443'
, path: '/'
, rejectUnauthorized: false
};


agent = new https.Agent(agentOptions);


request({
url: "https://www.example.com/api/endpoint"
, method: 'GET'
, agent: agent
}, function (err, resp, body) {
// ...
});

By using an agent with rejectUnauthorized you at least limit the security vulnerability to the requests that deal with that one site instead of making your entire node process completely, utterly insecure.

Other Options

If you were using a self-signed cert you would add this option:

agentOptions.ca = [ selfSignedRootCaPemCrtBuffer ];

For trusted-peer connections you would also add these 2 options:

agentOptions.key = clientPemKeyBuffer;
agentOptions.cert = clientPemCrtSignedBySelfSignedRootCaBuffer;

Bad Idea

It's unfortunate that process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; is even documented. It should only be used for debugging and should never make it into in sort of code that runs in the wild. Almost every library that runs atop https has a way of passing agent options through. Those that don't should be fixed.

I think the strictSSL: false should (should have worked, even in 2013) work. So in short are three possible ways:

  1. (obvious) Get your CA to renew the certificate, and put it on your server!
  2. Change the default settings of your request object:

    const myRequest = require('request').defaults({strictSSL: false})

    Many modules that use node-request internally also allow a request-object to be injected, so you can make them use your modified instance.
  3. (not recommended) Override all certificate checks for all HTTP(S) agent connections by setting the environment variable NODE_TLS_REJECT_UNAUTHORIZED=0 for the Node.js process.

Here is a more concise way to achieve the "less insecure" method proposed by CoolAJ86

request({
url: url,
agentOptions: {
rejectUnauthorized: false
}
}, function (err, resp, body) {
// ...
});

If someone is having this issue today while using an old version of nodejs, this might be due to Lets's encrypt 30th sept. 2021 ROOT CA expiry already mentionned in this answer.

certificates are hardcoded in node source code and the new ISRG Root X1 certificate was only added in this commit.

One can either update their node version, use node --use-openssl-ca flag (assuming openssl certificates are up to date), use the http agent solution mentionned in other answers (I didn't test it), or set process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0 as a quick and dirty workaround.

Updating Nodejs will force request's cache to be flushed.

This worked for me when nothing else did.