我已经开始为一个API编写包装,它要求所有请求都通过HTTPS.我希望在本地运行自己的服务器,模拟响应,而不是在开发和测试时向实际的API发出请求.

我对如何生成创建HTTPS服务器并向其发送请求所需的证书感到困惑.

我的服务器看起来像这样:

var options = {
  key: fs.readFileSync('./key.pem'),
  cert: fs.readFileSync('./cert.pem')
};

https.createServer(options, function(req, res) {
  res.writeHead(200);
  res.end('OK\n');
}).listen(8000);

pem文件是通过以下方式生成的:

openssl genrsa 1024 > key.pem
openssl req -x509 -new -key key.pem > cert.pem

请求看起来像这样:

var options = {
  host: 'localhost',
  port: 8000,
  path: '/api/v1/test'
};

https.request(options, function(res) {
  res.pipe(process.stdout);
}).end();

通过这个设置,我得到了Error: DEPTH_ZERO_SELF_SIGNED_CERT,所以我想我需要为请求添加一个ca选项.

所以我的问题是,我应该如何生成以下内容:

  1. 服务器key
  2. 服务器cert
  3. 请求的ca美元?

我读过一些关于使用openssl生成自签名证书的内容,但似乎不太明白该在 node 代码的何处使用哪些密钥和证书.

Update

API提供了一个CA证书来代替默认值使用.下面的代码使用他们的证书工作,这就是我想在本地复制的代码.

var ca = fs.readFileSync('./certificate.pem');

var options = {
  host: 'example.com',
  path: '/api/v1/test',
  ca: ca
};
options.agent = new https.Agent(options);

https.request(options, function(res) {
  res.pipe(process.stdout);
}).end();

推荐答案

Update (Nov 2018): Do you need self-signed certs?

还是真正的证书能让工作做得更好?你考虑过这些吗?

(Note: Let's Encrypt can also issue certificates to private networks)

ScreenCast

https://coolaj86.com/articles/how-to-create-a-csr-for-https-tls-ssl-rsa-pems/

Full, Working example

  • 创建证书
  • 运行 node .js服务器
  • node 中没有警告或错误.js客户端
  • cURL中没有警告或错误

https://github.com/coolaj86/nodejs-self-signed-certificate-example

localhost.greenlock.domains为例(它指向127.0.0.1):

服务器js

'use strict';

var https = require('https')
  , port = process.argv[2] || 8043
  , fs = require('fs')
  , path = require('path')
  , server
  , options
  ;

require('ssl-root-cas')
  .inject()
  .addFile(path.join(__dirname, 'server', 'my-private-root-ca.cert.pem'))
  ;

options = {
  // this is ONLY the PRIVATE KEY
  key: fs.readFileSync(path.join(__dirname, 'server', 'privkey.pem'))
  // You DO NOT specify `ca`, that's only for peer authentication
//, ca: [ fs.readFileSync(path.join(__dirname, 'server', 'my-private-root-ca.cert.pem'))]
  // This should contain both cert.pem AND chain.pem (in that order) 
, cert: fs.readFileSync(path.join(__dirname, 'server', 'fullchain.pem'))
};


function app(req, res) {
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello, encrypted world!');
}

server = https.createServer(options, app).listen(port, function () {
  port = server.address().port;
  console.log('Listening on https://127.0.0.1:' + port);
  console.log('Listening on https://' + server.address().address + ':' + port);
  console.log('Listening on https://localhost.greenlock.domains:' + port);
});

客户js

'use strict';

var https = require('https')
  , fs = require('fs')
  , path = require('path')
  , ca = fs.readFileSync(path.join(__dirname, 'client', 'my-private-root-ca.cert.pem'))
  , port = process.argv[2] || 8043
  , hostname = process.argv[3] || 'localhost.greenlock.domains'
  ;

var options = {
  host: hostname
, port: port
, path: '/'
, ca: ca
};
options.agent = new https.Agent(options);

https.request(options, function(res) {
  res.pipe(process.stdout);
}).end();

以及生成证书文件的脚本:

做证书.嘘

#!/bin/bash
FQDN=$1

# make directories to work from
mkdir -p server/ client/ all/

# Create your very own Root Certificate Authority
openssl genrsa \
  -out all/my-private-root-ca.privkey.pem \
  2048

# Self-sign your Root Certificate Authority
# Since this is private, the details can be as bogus as you like
openssl req \
  -x509 \
  -new \
  -nodes \
  -key all/my-private-root-ca.privkey.pem \
  -days 1024 \
  -out all/my-private-root-ca.cert.pem \
  -subj "/C=US/ST=Utah/L=Provo/O=ACME Signing Authority Inc/CN=example.com"

# Create a Device Certificate for each domain,
# such as example.com, *.example.com, awesome.example.com
# NOTE: You MUST match CN to the domain name or ip address you want to use
openssl genrsa \
  -out all/privkey.pem \
  2048

# Create a request from your Device, which your Root CA will sign
openssl req -new \
  -key all/privkey.pem \
  -out all/csr.pem \
  -subj "/C=US/ST=Utah/L=Provo/O=ACME Tech Inc/CN=${FQDN}"

# Sign the request from Device with your Root CA
openssl x509 \
  -req -in all/csr.pem \
  -CA all/my-private-root-ca.cert.pem \
  -CAkey all/my-private-root-ca.privkey.pem \
  -CAcreateserial \
  -out all/cert.pem \
  -days 500

# Put things in their proper place
rsync -a all/{privkey,cert}.pem server/
cat all/cert.pem > server/fullchain.pem         # we have no intermediates in this case
rsync -a all/my-private-root-ca.cert.pem server/
rsync -a all/my-private-root-ca.cert.pem client/

# create DER format crt for iOS Mobile Safari, etc
openssl x509 -outform der -in all/my-private-root-ca.cert.pem -out client/my-private-root-ca.crt

例如:

bash 做证书.嘘 'localhost.greenlock.domains'

希望这件事能让你如愿以偿.

还有一些解释:https://github.com/coolaj86/node-ssl-root-cas/wiki/Painless-Self-Signed-Certificates-in-node.js

Install private cert on iOS Mobile Safari

您需要使用DER格式创建根ca证书的副本.crt扩展:

# create DER format crt for iOS Mobile Safari, etc
openssl x509 -outform der -in all/my-private-root-ca.cert.pem -out client/my-private-root-ca.crt

然后,你可以简单地用你的Web服务器提供该文件.单击该链接时,系统会询问您是否要安装证书.

例如,你可以try 安装麻省理工学院的证书颁发机构:https://ca.mit.edu/mitca.crt

Related Examples

Node.js相关问答推荐

无法从ejs Web应用程序中的正文中提取数据

GraphQL MongoDB Mongoose填充字段未获取多个类别

一个函数中的两个依赖的NodeJS数据库操作.如果第二个失败了怎么办?

在 Docker 容器内创建一个 cron 作业(job)来执行 run.js 文件中的函数

Amplify 部署的应用程序出现TypeError: handler is not a function错误,但它在本地运行

结合后端(Express)和前端(Angular)路由

级联定时器和Jest 的异步功能

为什么我的 Cypress Post 请求的请求正文是空的?

Mongodb 从文档中获取聚合结果中的特定属性

NodeJS 后端发布请求将数据作为NULL值发布到 SQL Server 表

aws cdk 2.0 init 应用程序无法构建更漂亮的问题,这来自 jest-snapshot

Web3.js 脚本在监听 CreatedPairs 时退出

如何解决'npm应该在 node repl之外运行,在你的普通shell中'

npm WARN 不推荐使用 graceful-fs@3.0.8:graceful-fs 版本 3

Node.js `--nolazy` 标志是什么意思?

使用 Node.js 和 Express 进行简单的 API 调用

当进程被杀死时,如何优雅地关闭我的 Express 服务器?

响应分块时获取整个响应正文?

npm install packagename --save-dev 不更新 package.json

Mongoose:模式与模型?