如何配置 axios 使用 SSL 证书?

Posted

技术标签:

【中文标题】如何配置 axios 使用 SSL 证书?【英文标题】:How to configure axios to use SSL certificate? 【发布时间】:2018-12-24 02:54:28 【问题描述】:

我正在尝试使用 axios 向 api 端点发出请求,但出现以下错误:Error: unable to verify the first certificate

axios 使用的 https 模块似乎无法验证服务器上使用的 SSL 证书。

当用我的浏览器访问服务器时,证书是有效的,我可以看到/下载它。我也可以通过 https 向浏览器上的 api 发出请求。

我可以通过关闭验证来解决这个问题。此代码有效。

const result = await axios.post(
    `https://$url/login`,
    body,
    
      httpsAgent: new https.Agent(
        rejectUnauthorized: false
      )
    
  )

问题是,这不会验证 SSL 证书,因此会造成安全漏洞。

如何配置 axios 以信任证书并正确验证?

【问题讨论】:

使用 OkhttpClientFactory 的原生实现,***.com/a/60116643/2685454 【参考方案1】:

老问题,但对那些登陆这里的人来说很重要。没有专家。请咨询您当地的安全专家等等。

Axios 是一个 http(s) 客户端,http 客户端通常匿名参与 TLS。换句话说,服务器接受他们的连接而不识别谁正在尝试连接。这与说相互 TLS 不同,其中服务器和客户端在完成握手之前相互验证。

互联网是一个可怕的地方,我们希望保护我们的客户免于连接到欺骗性的公共端点。我们通过确保我们的客户在发送任何私人数据之前识别服务器来做到这一点。

// DO NOT DO THIS IF SHARING PRIVATE DATA WITH SERVICE
const httpsAgent = new https.Agent( rejectUnauthorized: false );

这通常作为 *** 上关于任何语言的 https 客户端连接失败的答案发布(并且受到更多人的反对)。更糟糕的是,它通常可以正常工作,解除对开发者的阻碍,然后他们继续愉快地前进。然而,虽然他们肯定进了门,但那是谁的门呢?由于他们选择不验证服务器的身份,因此他们可怜的客户端无法知道他们刚刚与公司内部网建立的连接是否有不良行为者在线监听。

如果服务具有公共 SSL 证书,https.Agent 通常不需要进一步配置,因为您的操作系统提供了一组公共受信任的公共 CA 证书。这通常是您的浏览器配置使用的同一组 CA 证书,这就是为什么默认 axios 客户端可以轻松点击https://google.com。

如果服务具有私有 SSL 证书(自签名用于测试目的或由您公司的私有 CA 签名以保护其内部机密),则必须将 https 代理配置为信任用于签署服务器证书的私有 CA:

const httpsAgent = new https.Agent( ca: MY_CA_BUNDLE );

其中MY_CA_BUNDLE 是一个 CA 证书数组,其中包含您要访问的端点的服务器证书以及该证书的完整证书链,格式为 .pem。您必须包含链中的所有证书,直到信任根。


这些选项记录在哪里?

HTTPS 是基于 TLS/SSL 的 HTTP 协议。在 Node.js 中,这是作为一个单独的模块实现的。

因此,传递给https.Agent 的选项是传递给tls.connect()tls.createSecureContext() 的选项的合并。

【讨论】:

在我下载了证书及其链后,这终于为我工作了。我之前失败了,因为我只下载了我想使用的服务的证书。对于像我一样苦苦挣扎的人:确保将整个链下载为 .pem。 @JemiSalo 如何获取我的自签名证书的整个链?我通过这样做来解决 id:const httpsAgent = new https.Agent( ca: fs.readFileSync(certPath) ); 这到底是在哪里记录的?我在 https.Agent 的文档中找不到对“ca”选项的任何引用。 @user1974458 它超级混乱,用选项的文档链接更新了答案 我真的很困惑。为什么我的浏览器可以信任私有 CA,但是从同一台机器上的节点脚本运行的 axios 却不行?!【参考方案2】:

使用 SSL 证书创建自定义代理:

const httpsAgent = new https.Agent(
  rejectUnauthorized: false, // (NOTE: this will disable client verification)
  cert: fs.readFileSync("./usercert.pem"),
  key: fs.readFileSync("./key.pem"),
  passphrase: "YYY"
)

axios.get(url,  httpsAgent )

// or

const instance = axios.create( httpsAgent )

来自https://github.com/axios/axios/issues/284

【讨论】:

rejectUnauthorized: false 禁用客户端验证,这是 OP 最关心的问题之一。 投了反对票,因为这不是 OP 要求的。这个答案虽然仍然正确(除了关于rejectUnauthorized),但与客户端证书有关,OP 想要验证服务器证书 另外我觉得key参数有点奇怪,那个key是什么? 我们可以从哪里导入 https ??在反应原生【参考方案3】:

这些配置对我有用(在相互身份验证场景中)。

const httpsAgent = new https.Agent(
  ca: fs.readFileSync("./resource/bundle.crt"),        
  cert: fs.readFileSync("./resrouce/thirdparty.crt"),
  key: fs.readFileSync("./resource/key.pem"), 
)

注意:bundle.crt 是根据提供的证书(根证书、中间证书、最终入口证书)准备的。不幸的是,在这方面没有找到明确的文档。

【讨论】:

要创建一个捆绑包,只需将提供的证书内容以相反的顺序复制到一个文本文件中。在unix 中,命令将在您的情况下为:cat thirdparty.crt other.crt > bundle.crt,其中捆绑包的名称并不重要。 请告诉我 other.crt 是什么? @rawplutonium【参考方案4】:

对我来说,当我的应用程序在开发模式下运行时,我直接在axios.defaults.options 中禁用了rejectUnauthorized。这很好用。请小心,仅在开发人员模式下使用它。

import https from 'https'
import axios from 'axios'
import config from '~/config'

/**
 * Axios default settings
 */
axios.defaults.baseURL = config.apiURL

/**
 * Disable only in development mode
 */
if (process.env.NODE_ENV === 'development') 
  const httpsAgent = new https.Agent(
    rejectUnauthorized: false,
  )
  axios.defaults.httpsAgent = httpsAgent
  // eslint-disable-next-line no-console
  console.log(process.env.NODE_ENV, `RejectUnauthorized is disabled.`)

【讨论】:

应该注意,如果您的服务器位于localhost,这是安全的,但在通过互联网调用公共端点时不安全。 谢谢。这对我有用,但必须将 axios.defaults.options 更改为 axios.defaults.httpsAgent 谢谢我已经修好了。 您从哪里导入了 https?在 React Native 中 @ShafqatBari https 模块来自 nodejs。【参考方案5】:

这对我有用,使用带有 nodejs + express 的 axios

exports.test_ssl = async (req,res) =>  
   
let cert_file = fs.readFileSync("./ssl/my_self_signed_certificate.crt")
let ca_file = fs.readFileSync("./ssl/my_self_signed_certificate_ca.crt")
const agent = new https.Agent(
    requestCert: true,
    rejectUnauthorized: true,
    cert: cert_file,
    ca: ca_file
);
const options = 
    url: `https://51.195.45.154/test`,  // <---this is  a fake ip do not bother
    method: "POST",
    httpsAgent : agent,
    headers: 
        'Accept': 'application/json',
        'Content-Type': 'application/txt;charset=UTF-8'
    ,
    data: 
;


console.log(cert_file.toString())

axios(options)
.then(response => 
    payload = response.data ;
    return res.status(200).send("status":1);
).catch(err => 
    console.log(err);
    return false
);


【讨论】:

这个答案有rejectUnauthorized: false,它会关闭服务器的身份检查并将您的客户端暴露给中间人攻击。请参阅已接受的答案,您不应该在生产工作负载中这样做。 @srquinn 感谢修复【参考方案6】:

这对我有用:

import axios from 'axios'
import https from 'https'

const headers = ;

const httpsAgent = new https.Agent(
  ca: fs.readFileSync('./certs/cert.pem'),
  cert: fs.readFileSync('./certs/cert.pem'),
)

const data = await axios.get(url,  httpsAgent, headers )

【讨论】:

您从哪里导入了 https?在 React Native 中 它是一个 nodejs 核心模块,在 react-native 中不起作用【参考方案7】:
const https = require('https');
const axios = require('axios')

const CA = "-----BEGIN CERTIFICATE-----$$$$$-----END CERTIFICATE-----"
const url = "bla"
const httpsAgent = new https.Agent(
  ca: CA
);

const response = await axios.get(url,  httpsAgent );

这对我有用。

【讨论】:

您从哪里导入了 https?在 React Native 中【参考方案8】:

这很脏,但在你的脚本的顶部,只要放:

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

这基本上告诉节点不要检查 SSL 证书,当您在开发中遇到自签名证书被拒绝时,这非常方便。

请不要在生产中使用它。

【讨论】:

【参考方案9】:

亲爱的早安。

我的问题如下:

“启用验证第一个证书”,错误代码为“ENABLE_TO_VERIFY_LEAF_SIGNATURE”。

他们向我发送了带有 .pfx 扩展名的证书,并使用以下命令生成了 .pem 证书和带有 .pem 扩展名的密钥。

我附上命令。

openssl pkcs12 -in certificate.pfx -nocerts -out key.pem -nodes openssl pkcs12 -in certificate.pfx -nokeys -out certificate.pem

需要注意的是,我是使用axios来发出请求的。

我在 axios 中附加了我的代理配置。

const httpsAgent = 新 https.Agent ( pfx:fs.readFileSync(“path.pfx”), 密码:'密码', 请求证书:真, 拒绝未授权:真 );

【讨论】:

以上是关于如何配置 axios 使用 SSL 证书?的主要内容,如果未能解决你的问题,请参考以下文章

如何诊断自己的网站 SSL 证书配置正确与否?

nginx下如何配置 ssl证书?腾讯云ssl证书为例!

如何使用别名在 Apache 虚拟主机上配置多个 SSL 证书?

如何正确的配置ssl证书,配置ssl有哪些好处

如何配置https安全证书,ssl证书如何配置

我配置好一个tomcat,ssl证书,如何给同一台机器上的其他tomcat配置证书,默认的80,443端口已经被占用。