在node.js中使用http .request忽略无效的自签名ssl证书?

我正在开发一个小应用程序,可以登录到我的本地无线路由器(Linksys),但我遇到了路由器自签名ssl证书的问题。

我运行wget 192.168.1.1,得到:

ERROR: cannot verify 192.168.1.1's certificate, issued by `/C=US/ST=California/L=Irvine/O=Cisco-Linksys, LLC/OU=Division/CN=Linksys/emailAddress=support@linksys.com':
Self-signed certificate encountered.
ERROR: certificate common name `Linksys' doesn't match requested host name `192.168.1.1'.
To connect to 192.168.1.1 insecurely, use `--no-check-certificate'.

在node中,被捕获的错误是:

{ [Error: socket hang up] code: 'ECONNRESET' }

我目前的示例代码是:

var req = https.request({
host: '192.168.1.1',
port: 443,
path: '/',
method: 'GET'


}, function(res){


var body = [];
res.on('data', function(data){
body.push(data);
});


res.on('end', function(){
console.log( body.join('') );
});


});
req.end();


req.on('error', function(err){
console.log(err);
});

我如何才能让node.js做等效的“——no-check-certificate”?

529791 次浏览

在您的请求选项中,尝试包括以下内容:

   var req = https.request({
host: '192.168.1.1',
port: 443,
path: '/',
method: 'GET',
rejectUnauthorized: false,
requestCert: true,
agent: false
},

或者你可以尝试在本地名称解析中添加(在大多数操作系统中,hosts文件在etc目录中找到,细节不同)这样的东西:

192.168.1.1 Linksys

和明年

var req = https.request({
host: 'Linksys',
port: 443,
path: '/',
method: 'GET'
...

将工作。

廉价又不可靠的回答:

添加

process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;

在代码中调用https.request()之前

一个更安全的方法(上面的解决方案使整个节点进程不安全)在问题中回答

添加如下环境变量:

NODE_TLS_REJECT_UNAUTHORIZED=0

例如,用export:

export NODE_TLS_REJECT_UNAUTHORIZED=0

(非常感谢Juanra)

对于meteorJS,你可以设置npmRequestOptions。

HTTP.post(url, {
npmRequestOptions: {
rejectUnauthorized: false // TODO remove when deploy
},
timeout: 30000, // 30s
data: xml
}, function(error, result) {
console.log('error: ' + error);
console.log('resultXml: ' + result);
});

补充@Armand的回答:

添加如下环境变量:

NODE_TLS_REJECT_UNAUTHORIZED=0例如:

export NODE_TLS_REJECT_UNAUTHORIZED=0(非常感谢Juanra)

如果你了解windows的使用情况:

set NODE_TLS_REJECT_UNAUTHORIZED=0

感谢:@weagle08

不要相信所有试图误导你的人。

在您的请求中,只需添加:

ca: [fs.readFileSync([certificate path], {encoding: 'utf-8'})]

如果您打开未经授权的证书,您将完全得不到保护(由于未验证身份而暴露在MITM中),并且在没有SSL的情况下工作也不会有太大区别。解决方案是指定您期望的CA证书,如下一个代码片段所示。确保证书的公共名称与您在请求中调用的地址相同(与主机中指定的地址相同):

你会得到的是:

var req = https.request({
host: '192.168.1.1',
port: 443,
path: '/',
ca: [fs.readFileSync([certificate path], {encoding: 'utf-8'})],
method: 'GET',
rejectUnauthorized: true,
requestCert: true,
agent: false
},

请在这里阅读这篇文章(披露:由这个答案的作者撰写的博客文章)以理解:

  • CA证书的工作原理
  • 如何生成CA证书以方便测试以模拟生产环境

你也可以用默认选项创建一个请求实例:

require('request').defaults({ rejectUnauthorized: false })
< p >试 出口NODE_TLS_REJECT_UNAUTHORIZED = 0 < / p >
所以,我的公司刚刚切换到Node.js v12.x。 我正在使用NODE_TLS_REJECT_UNAUTHORIZED,它停止工作。 经过一番挖掘,我开始使用NODE_EXTRA_CA_CERTS=A_FILE_IN_OUR_PROJECT,它具有自签名证书的PEM格式,所有脚本都重新工作了

所以,如果你的项目有自签名的证书,也许这个env var会帮助你。

裁判:https://nodejs.org/api/cli.html#cli_node_extra_ca_certs_file

当您无法控制请求的创建时

当使用包时,你有时没有在request调用上设置正确设置的选项,包也没有为你提供注入request的方法。

然而,你可能仍然想要避免不安全的NODE_TLS_REJECT_UNAUTHORIZED=0,并选择只使用到指定目标的不安全连接。

我是这样解决这个问题的:

// check if host and port fit your application
function isSelf(host, port) {
return host === myHost && port === myPort;
}


// get the built in tls module and overwrite the default connect behavior
const tls = require("tls");
const _connect = tls.connect;
function wrappedConnect(options, secureConnectListener) {
if (isSelf(options.host, options.port)) {
options.rejectUnauthorized = false;
}
return _connect(options, secureConnectListener);
}
tls.connect = wrappedConnect;

如果您正在使用@nestjs/axios寻找帖子,

以下是没有证书的语法(非生产解决方案):

const token = Buffer.from(`${user}:${password}`,'utf8').toString('base64')


const config = {
headers: {
'Content-Type': 'application/json',
Authorization: `Basic ${token}`,
},
httpsAgent: new https.Agent({
rejectUnauthorized: false
}),
};


const responseData = await firstValueFrom(
this.httpService.post(url, data, config).pipe(map((response) => response.data)),
);

以下是certificate的语法(生产解决方案):

const token = Buffer.from(`${user}:${password}`,'utf8').toString('base64')


const config = {
headers: {
'Content-Type': 'application/json',
Authorization: `Basic ${token}`,
},
httpsAgent: new https.Agent({
rejectUnauthorized: true,
ca: fs.readFileSync(path.join(__dirname, './resources/certificateName'))
}),
};


const responseData = await firstValueFrom(
this.httpService.post(url, data, config).pipe(map((response) => response.data)),
);