我正在尝试让 HTTPS 在 node 的 express.js 上运行,但我无法弄清楚。
这是我的 app.js
代码。
var express = require('express');
var fs = require('fs');
var privateKey = fs.readFileSync('sslcert/server.key');
var certificate = fs.readFileSync('sslcert/server.crt');
var credentials = {key: privateKey, cert: certificate};
var app = express.createServer(credentials);
app.get('/', function(req,res) {
res.send('hello');
});
app.listen(8000);
当我运行它时,它似乎只响应 HTTP 请求。
我编写了简单的基于香草 node.js
的 HTTPS 应用程序:
var fs = require("fs"),
http = require("https");
var privateKey = fs.readFileSync('sslcert/server.key').toString();
var certificate = fs.readFileSync('sslcert/server.crt').toString();
var credentials = {key: privateKey, cert: certificate};
var server = http.createServer(credentials,function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
});
server.listen(8000);
当我运行这个应用程序时,它会响应 HTTPS 请求。请注意,我认为 fs 结果上的 toString() 并不重要,因为我使用了两者的组合,但仍然没有 es bueno。
编辑添加:
对于生产系统,您最好使用 Nginx 或 HAProxy 将请求代理到您的 nodejs 应用程序。您可以设置 nginx 来处理 ssl 请求,只需将 http 与您的节点 app.js 对话即可。
编辑添加(2015 年 4 月 6 日)
对于使用 AWS 的系统,您最好使用 EC2 弹性负载均衡器来处理 SSL 终止,并允许定期 HTTP 流量到您的 EC2 Web 服务器。为了进一步安全,请设置您的安全组,以便只允许 ELB 将 HTTP 流量发送到 EC2 实例,这将防止外部未加密的 HTTP 流量到达您的计算机。
在 express.js(自版本 3 起)中,您应该使用该语法:
var fs = require('fs');
var http = require('http');
var https = require('https');
var privateKey = fs.readFileSync('sslcert/server.key', 'utf8');
var certificate = fs.readFileSync('sslcert/server.crt', 'utf8');
var credentials = {key: privateKey, cert: certificate};
var express = require('express');
var app = express();
// your express configuration here
var httpServer = http.createServer(app);
var httpsServer = https.createServer(credentials, app);
httpServer.listen(8080);
httpsServer.listen(8443);
通过这种方式,您可以向本机 http/https 服务器提供快速中间件
如果您希望您的应用程序在低于 1024 的端口上运行,则需要使用 sudo
命令(不推荐)或使用反向代理(例如 nginx、haproxy)。
首先,您需要创建 selfsigned.key 和 selfsigned.crt 文件。转至 Create a Self-Signed SSL Certificate 或执行以下步骤。
转到终端并运行以下命令。
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./selfsigned.key -out selfsigned.crt
之后输入以下信息
国家名称(2 个字母代码)[AU]:美国
州或省名称(全名)[Some-State]:NY
地区名称(例如,城市)[]:NY
组织名称(例如,公司)[Internet Widgits Pty Ltd]:xyz(您的组织)
组织单位名称(例如,部分)[]:xyz(您的单位名称)
通用名称(例如服务器 FQDN 或您的姓名)[]:www.xyz.com(您的 URL)
电子邮件地址 []:您的电子邮件
创建后在您的代码中添加密钥和证书文件,并将选项传递给服务器。
const express = require('express');
const https = require('https');
const fs = require('fs');
const port = 3000;
var key = fs.readFileSync(__dirname + '/../certs/selfsigned.key');
var cert = fs.readFileSync(__dirname + '/../certs/selfsigned.crt');
var options = {
key: key,
cert: cert
};
app = express()
app.get('/', (req, res) => {
res.send('Now using https..');
});
var server = https.createServer(options, app);
server.listen(port, () => {
console.log("server starting on port : " + port)
});
最后使用 https 运行您的应用程序。
更多信息 https://github.com/sagardere/set-up-SSL-in-nodejs
sudo chown ubuntu -R /etc/letsencrypt
并且它有效。ubuntu 是用户name 你可以用用户名替换它。
'/../certs/selfsigned.key'
这样的硬编码路径,我想知道如何让 readFileSync 工作。查看问题:stackoverflow.com/questions/56744208/…
我在让 SSL 在端口 443 以外的端口上工作时遇到了类似的问题。在我的情况下,我有一个捆绑证书以及一个证书和一个密钥。捆绑证书是一个包含多个证书的文件,节点要求您将这些证书分解为数组的单独元素。
var express = require('express');
var https = require('https');
var fs = require('fs');
var options = {
ca: [fs.readFileSync(PATH_TO_BUNDLE_CERT_1), fs.readFileSync(PATH_TO_BUNDLE_CERT_2)],
cert: fs.readFileSync(PATH_TO_CERT),
key: fs.readFileSync(PATH_TO_KEY)
};
app = express()
app.get('/', function(req,res) {
res.send('hello');
});
var server = https.createServer(options, app);
server.listen(8001, function(){
console.log("server running at https://IP_ADDRESS:8001/")
});
在 app.js 中,您需要指定 https 并相应地创建服务器。此外,请确保您尝试使用的端口实际上允许入站流量。
PATH_TO_BUNDLE_CERT_1
这样的变量,我想知道如何让 readFileSync 工作。查看问题:stackoverflow.com/questions/56744208/…
包括积分:
SSL 设置 在 config/local.js 在 config/env/production.js
HTTP 和 WS 处理
该应用程序必须在开发中运行在 HTTP 上,以便我们可以轻松地调试我们的应用程序。出于安全考虑,该应用程序必须在生产环境中在 HTTPS 上运行。应用程序生产 HTTP 请求应始终重定向到 https。
SSL 配置
在 Sailsjs 中,有两种配置所有东西的方法,第一种是在 config 文件夹中进行配置,每个文件都有其单独的文件(例如有关设置的数据库连接位于 connections.js 中)。其次是配置环境基础文件结构,每个环境文件都出现在 config/env
文件夹中,每个文件都包含特定环境的设置。
Sails 首先查看 config/env 文件夹,然后期待 config/ *.js
现在让我们在 config/local.js
中设置 ssl。
var local = {
port: process.env.PORT || 1337,
environment: process.env.NODE_ENV || 'development'
};
if (process.env.NODE_ENV == 'production') {
local.ssl = {
secureProtocol: 'SSLv23_method',
secureOptions: require('constants').SSL_OP_NO_SSLv3,
ca: require('fs').readFileSync(__dirname + '/path/to/ca.crt','ascii'),
key: require('fs').readFileSync(__dirname + '/path/to/jsbot.key','ascii'),
cert: require('fs').readFileSync(__dirname + '/path/to/jsbot.crt','ascii')
};
local.port = 443; // This port should be different than your default port
}
module.exports = local;
或者,您也可以在 config/env/production.js 中添加它。 (此片段还显示了如何处理多个 CARoot 证书)
或者在 production.js 中
module.exports = {
port: 443,
ssl: {
secureProtocol: 'SSLv23_method',
secureOptions: require('constants').SSL_OP_NO_SSLv3,
ca: [
require('fs').readFileSync(__dirname + '/path/to/AddTrustExternalCARoot.crt', 'ascii'),
require('fs').readFileSync(__dirname + '/path/to/COMODORSAAddTrustCA.crt', 'ascii'),
require('fs').readFileSync(__dirname + '/path/to/COMODORSADomainValidationSecureServerCA.crt', 'ascii')
],
key: require('fs').readFileSync(__dirname + '/path/to/jsbot.key', 'ascii'),
cert: require('fs').readFileSync(__dirname + '/path/to/jsbot.crt', 'ascii')
}
};
http/https & ws/wss 重定向
这里 ws 是 Web Socket,wss 代表 Secure Web Socket,因为我们设置了 ssl,然后现在 http 和 ws 两个请求都变得安全并分别转换为 https 和 wss。
我们的应用程序有很多来源会像任何博客文章、社交媒体文章一样接收请求,但我们的服务器仅在 https 上运行,因此当任何来自 http 的请求时,它会在客户端浏览器中显示“无法访问此站点”错误。我们失去了我们的网站流量。所以我们必须将http请求重定向到https,同样的规则允许websocket,否则socket会失败。
所以我们需要在 80 端口(http)上运行相同的服务器,并将所有请求转移到 443(https)端口。 Sails 在提升服务器之前首先编译 config/bootstrap.js 文件。在这里,我们可以在端口 80 上启动我们的 express 服务器。
在 config/bootstrap.js 中(创建 http 服务器并将所有请求重定向到 https)
module.exports.bootstrap = function(cb) {
var express = require("express"),
app = express();
app.get('*', function(req, res) {
if (req.isSocket)
return res.redirect('wss://' + req.headers.host + req.url)
return res.redirect('https://' + req.headers.host + req.url)
}).listen(80);
cb();
};
现在您可以访问 http://www.yourdomain.com,它会重定向到 https://www.yourdomain.com
这就是它为我工作的方式。使用的重定向也将重定向所有正常的http。
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const http = require('http');
const app = express();
var request = require('request');
//For https
const https = require('https');
var fs = require('fs');
var options = {
key: fs.readFileSync('certificates/private.key'),
cert: fs.readFileSync('certificates/certificate.crt'),
ca: fs.readFileSync('certificates/ca_bundle.crt')
};
// API file for interacting with MongoDB
const api = require('./server/routes/api');
// Parsers
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// Angular DIST output folder
app.use(express.static(path.join(__dirname, 'dist')));
// API location
app.use('/api', api);
// Send all other requests to the Angular app
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
app.use(function(req,resp,next){
if (req.headers['x-forwarded-proto'] == 'http') {
return resp.redirect(301, 'https://' + req.headers.host + '/');
} else {
return next();
}
});
http.createServer(app).listen(80)
https.createServer(options, app).listen(443);
const https = require('https').Server(app);
并尝试了这条 https.createServer(options,app);
那是我不断收到 createServer is not function 错误的时候。然后,仔细研究像你这样的例子。然后我明白了为什么我有问题。我只需要这个 const https = require('https');
谢谢您的回复。
使用 greenlock-express:免费 SSL、自动 HTTPS
Greenlock 处理证书颁发和更新(通过 Let's Encrypt)和 http => https 重定向,开箱即用。
express-app.js
:
var express = require('express');
var app = express();
app.use('/', function (req, res) {
res.send({ msg: "Hello, Encrypted World!" })
});
// DO NOT DO app.listen()
// Instead export your app:
module.exports = app;
server.js
:
require('greenlock-express').create({
// Let's Encrypt v2 is ACME draft 11
version: 'draft-11'
, server: 'https://acme-v02.api.letsencrypt.org/directory'
// You MUST change these to valid email and domains
, email: 'john.doe@example.com'
, approveDomains: [ 'example.com', 'www.example.com' ]
, agreeTos: true
, configDir: "/path/to/project/acme/"
, app: require('./express-app.j')
, communityMember: true // Get notified of important updates
, telemetry: true // Contribute telemetry data to the project
}).listen(80, 443);
截屏
观看快速入门演示:https://youtu.be/e8vaR4CEZ5s
https://i.imgur.com/Y8ix6Ts.png
对于本地主机
只是提前回答这个问题,因为这是一个常见的后续问题:
您不能在本地主机上拥有 SSL 证书。但是,您可以使用 Telebit 之类的东西,这样您就可以将本地应用程序作为真实应用程序运行。
您还可以通过 DNS-01 挑战将私有域与 Greenlock 一起使用,自述文件中提到了该挑战以及支持它的各种插件。
非标准端口(即没有 80 / 443)
阅读上面关于 localhost 的注释 - 您也不能在 Let's Encrypt 中使用非标准端口。
但是,您可以通过端口转发、sni-route 将内部非标准端口公开为外部标准端口,或者使用 Telebit 之类的东西为您执行 SNI 路由和端口转发/中继。
您还可以使用 DNS-01 挑战,在这种情况下您根本不需要公开端口,并且您还可以通过这种方式保护专用网络上的域。
这个答案与 Setthase 非常相似,但它适用于 LetsEncrypt (Ubuntu)
// Dependencies
const fs = require('fs');
const http = require('http');
const https = require('https');
const express = require('express');
const app = express();
// Certificate
const privateKey = fs.readFileSync('/etc/letsencrypt/live/yourdomain.com/privkey.pem', 'utf8');
const certificate = fs.readFileSync('/etc/letsencrypt/live/yourdomain.com/cert.pem', 'utf8');
const ca = fs.readFileSync('/etc/letsencrypt/live/yourdomain.com/chain.pem', 'utf8');
const credentials = {
key: privateKey,
cert: certificate,
ca: ca
};
app.use((req, res) => {
res.send('Hello there !');
});
// Starting both http & https servers
const httpServer = http.createServer(app);
const httpsServer = https.createServer(credentials, app);
httpServer.listen(80, () => {
console.log('HTTP Server running on port 80');
});
httpsServer.listen(443, () => {
console.log('HTTPS Server running on port 443');
});
您可能会遇到:EACCES:权限被拒绝,打开 '/etc/letsencrypt/live/yourdeomain.com/privkey.pem'
对我有用的是在 ubuntu ssh 终端获取用户 whoami
// Create group with root and nodeuser as members
$ sudo addgroup nodecert
$ sudo adduser ubuntu nodecert
$ sudo adduser root nodecert
// Make the relevant letsencrypt folders owned by said group.
$ sudo chgrp -R nodecert /etc/letsencrypt/live
$ sudo chgrp -R nodecert /etc/letsencrypt/archive
// Allow group to open relevant folders
$ sudo chmod -R 750 /etc/letsencrypt/live
$ sudo chmod -R 750 /etc/letsencrypt/archive
sudo reboot
不要忘记凭据中的 PEM 密码短语!
当您使用 OpenSSL 生成凭据时(不要忘记 -sha256
标志):
OpenSSL> req -x509 -sha256 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365
Generating a RSA private key
writing new private key to 'key.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
您的 JS/TS 代码:
const credentials = {key: privateKey, cert: certificate, passphrase: 'YOUR passphrase'};
您还可以使用 node-forge 生成自签名证书
在下面的代码中,在启动时会生成一个新证书,这意味着您每次重新启动服务器时都会获得一个新证书。
const https = require('https')
const express = require('express')
const forge = require('node-forge')
;(function main() {
const server = https.createServer(
generateX509Certificate([
{ type: 6, value: 'http://localhost' },
{ type: 7, ip: '127.0.0.1' }
]),
makeExpressApp()
)
server.listen(8443, () => {
console.log('Listening on https://localhost:8443/')
})
})()
function generateX509Certificate(altNames) {
const issuer = [
{ name: 'commonName', value: 'example.com' },
{ name: 'organizationName', value: 'E Corp' },
{ name: 'organizationalUnitName', value: 'Washington Township Plant' }
]
const certificateExtensions = [
{ name: 'basicConstraints', cA: true },
{ name: 'keyUsage', keyCertSign: true, digitalSignature: true, nonRepudiation: true, keyEncipherment: true, dataEncipherment: true },
{ name: 'extKeyUsage', serverAuth: true, clientAuth: true, codeSigning: true, emailProtection: true, timeStamping: true },
{ name: 'nsCertType', client: true, server: true, email: true, objsign: true, sslCA: true, emailCA: true, objCA: true },
{ name: 'subjectAltName', altNames },
{ name: 'subjectKeyIdentifier' }
]
const keys = forge.pki.rsa.generateKeyPair(2048)
const cert = forge.pki.createCertificate()
cert.validity.notBefore = new Date()
cert.validity.notAfter = new Date()
cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1)
cert.publicKey = keys.publicKey
cert.setSubject(issuer)
cert.setIssuer(issuer)
cert.setExtensions(certificateExtensions)
cert.sign(keys.privateKey)
return {
key: forge.pki.privateKeyToPem(keys.privateKey),
cert: forge.pki.certificateToPem(cert)
}
}
function makeExpressApp() {
const app = express()
app.get('/', (req, res) => {
res.json({ message: 'Hello, friend' })
})
return app
}
这是我的 express 4.0 工作代码。
express 4.0 与 3.0 和其他版本有很大不同。
4.0 你有 /bin/www 文件,你要在这里添加 https。
“npm start”是启动 express 4.0 服务器的标准方式。
readFileSync() 函数应该使用 __dirname 获取当前目录
而 require() 使用 ./ 引用当前目录。
首先你把 private.key 和 public.cert 文件放在 /bin 文件夹下,它和 WWW 文件是同一个文件夹。
localhost:80
但不适用于https://localhost:443