在node.js中使用rejectUnauthorized和node-fetch

14

我目前在node.js中使用request来进行HTTP请求。曾经遇到过一个问题,错误提示为 UNABLE_TO_GET_ISSUER_CERT_LOCALLY。为了绕过这个问题,我设置了rejectUnauthorized选项。我的工作代码如下:

    var url = 'someurl';
    var options = {
        url: url,
        port: 443,
        // proxy: process.env.HTTPS_PROXY, -- no need to do this as request honors env vars
        headers: {
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko',
            'Accept-Language': 'en-us',
            'Content-Language': 'en-us'
        },
        timeout: 0,
        encoding: null,
        rejectUnauthorized: false // added this to prevent the UNABLE_TO_GET_ISSUER_CERT_LOCALLY error
    };
    request(options, function (err, resp, body) {
        if (err) reject(err);
        else resolve(body.toString());
    });

我想尝试使用async/await切换到fetch api,现在正在尝试使用node-fetch执行相同的操作。然而,当我做同样的事情时,我又遇到了“UNABLE_TO_GET_ISSUER_CERT_LOCALLY”错误。我读到需要使用代理代理器(proxy agent),并尝试使用proxy-agent模块,但仍然没有成功。

根据https://github.com/TooTallNate/node-https-proxy-agent/issues/11的帖子,我认为以下内容应该有效:

    var options = {
        headers: {
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko',
            'Accept-Language': 'en-us',
            'Content-Language': 'en-us'
        },
        timeout: 0,
        encoding: null
    };
    var proxyOptions = nodeurl.parse(process.env.HTTPS_PROXY);
    proxyOptions.rejectUnauthorized = false;
    options.agent = new ProxyAgent(proxyOptions);
    const resp = await fetch('someurl', options);
    return await resp.text();

但我仍然遇到相同的错误。到目前为止,我唯一能够使用node-fetch解决这个问题的方式是在我的环境中设置NODE_TLS_REJECT_UNAUTHORIZED=0,但我确实不想这样做。有人可以帮助我展示如何使用node-fetch让rejectUnauthorized工作(可能使用代理,但我只要求它作为请求的一部分被指定)。


1
尝试使用隧道模块,它会起作用!新版本的node-https-proxy-agent存在问题!您可以使用旧版本3.x及以下版本!它会起作用!否则只需使用隧道模块!这是我的经验和我如何使其工作的! - Mohamed Allal
我也更新了问题!它包含一个很好的例子和可能有趣的包(我在node-tunnel上制作的包装器)https://www.npmjs.com/package/proxy-http-agent - Mohamed Allal
你只需要将此代码添加到你的fetch选项中:agent: httpsAgent, - chovy
你只需要将这段代码添加到你的fetch选项中:agent: httpsAgent, - undefined
2个回答

9
⚠️ 请注意,使用rejectUnauthorized是危险的,因为它会使您面临潜在的安全风险,绕过了一个有问题的证书。
以下是我在Node.js应用程序中使用rejectUnauthorizedFetch API解决证书错误的方法。
const fetch = require("node-fetch");
const https = require('https');

const httpsAgent = new https.Agent({
  rejectUnauthorized: false,
});

async function getData() {
  const resp = await fetch(
    "https://myexampleapi.com/endpoint",
    {
      agent: httpsAgent,
    },
  )
  const data = await resp.json()
  return data
}

如果你的应用程序是一个“模块”,你可能需要使用 npm i httpsimport https from 'https'; - John Meyer
另外,您可以执行 const resp = await fetch('https://example.com', { agent: new https.Agent({ rejectUnauthroized: false }) }); - John Meyer

2

使用代理

您需要知道,node-https-proxy-agent最新版本存在问题,无法与Fetch一起使用!您可以使用旧版本3.x及以下版本!它将能够正常工作!否则,您可以使用node-tunnel模块https://www.npmjs.com/package/tunnel!您也可以使用基于node-tunnel的包装模块proxy-http-agenthttps://www.npmjs.com/package/proxy-http-agent!它提供了代理协议的自动检测!一个方法适用于所有情况!而且两者都支持http和https!

您可以在此模块和仓库中查看用法,并查看代理构建和设置的示例(请查看测试): https://www.npmjs.com/package/net-proxy https://github.com/Glitnirian/node-net-proxy#readme

例如:

import { ProxyServer } from 'net-proxy';
import { getProxyHttpAgent } from 'proxy-http-agent';

// ...

// __________ setting the proxy

const proxy = new ProxyServer({
    port: proxyPort
});
 
proxy.server.on('data', (data: any) => { // accessing the server instance
    console.log(data);
});
 
await proxy.awaitStartedListening(); // await server to start
 
// After server started
 
// ______________ making the call through the proxy to a server through http:

let proxyUrl = `http://localhost:${proxyPort}`; // Protocol from the proxy is automatically detected

let agent = getProxyHttpAgent({
    proxy: proxyUrl,
    endServerProtocol: 'http:' // the end server protocol (http://localhost:${localApiServerPort} for example)
});
 
const response = await fetch(`http://localhost:${localApiServerPort}`, {
    method: 'GET',
    agent 
});

// ___________________ making a call through the proxy to a server through https:

agent = getProxyHttpAgent({
    proxy: proxyUrl, // proxy as url string! We can use an object (as tunnel module require too)
    rejectUnauthorized: false // <==== here it go
});

const response2 = await fetch(`https://localhost:${localApiHttpsServerPort}`, {
    method: 'GET',
    agent
});

您可以在此文档中查看更多示例和详细信息:

https://www.npmjs.com/package/proxy-http-agent

您也可以直接使用node-tunnel!但该软件包只是一个简单的包装器!这使得它更加简单易用!

添加rejectUnauthorized

对于不太了解的人!

根据此线程

https://github.com/node-fetch/node-fetch/issues/15

我们使用https.Agent来传递rejectUnauthorized参数!

const agent = new https.Agent({
  key: fs.readFileSync(`${CERT_PATH}.key`),
  cert: fs.readFileSync(`${CERT_PATH}.crt`),
  rejectUnauthorized: false
})

一个完整的示例
import https from "https";
const agent = new https.Agent({
  rejectUnauthorized: false
});
fetch(myUrl, { agent });

对于fetch,您也可以使用环境变量,如下所示:

process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";

这样设置可以全局生效,而不是每次调用都需要设置。如果您使用的是常量代理,则可能更合适!对于所有调用!因为当位于公司代理后面时!

为什么

默认情况下,Node Fetch!以及大多数HTTP请求客户端!在使用https时都使用安全性并确保有效的SSL证书! 要禁用此行为,我们需要以某种方式禁用该检查! 根据库的不同,它可能是不同的!

对于fetch,就是这样完成的!

使用http.request!(底层)

const https = require('https');

const options = {
  hostname: 'encrypted.google.com',
  port: 443,
  path: '/',
  method: 'GET',
  rejectUnauthorized: false /// <<<== here
};

const req = https.request(options, (res) => {
  console.log('statusCode:', res.statusCode);
  console.log('headers:', res.headers);

  res.on('data', (d) => {
    process.stdout.write(d);
  });
});

req.on('error', (e) => {
  console.error(e);
});
req.end();

请看这个链接:https://nodejs.org/api/https.html#https_https_request_url_options_callback。它也是tls.connect选项的一部分,你可以在这里查看:https://nodejs.org/api/tls.html#tls_tls_connect_options_callback

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接