node.js 在 express.js 上启用 HTTPS
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11744975/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Enabling HTTPS on express.js
提问by Alan
I'm trying to get HTTPS working on express.js for node, and I can't figure it out.
我正在尝试让 HTTPS 在 node 的 express.js 上工作,但我无法弄清楚。
This is my app.jscode.
这是我的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);
When I run it, it seems to only respond to HTTP requests.
当我运行它时,它似乎只响应 HTTP 请求。
I wrote simple vanilla node.jsbased HTTPS app:
我写了一个简单的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);
And when I run this app, it doesrespond to HTTPS requests. Note that I don't think the toString() on the fs result matters, as I've used combinations of both and still no es bueno.
当我运行这个应用程序时,它会响应 HTTPS 请求。请注意,我认为 fs 结果上的 toString() 并不重要,因为我使用了两者的组合,但仍然没有 es bueno。
EDIT TO ADD:
编辑添加:
For production systems, you're probably better off using Nginx or HAProxy to proxy requests to your nodejs app. You can setup nginx to handle the ssl requests and just speak http to your node app.js.
对于生产系统,您最好使用 Nginx 或 HAProxy 将请求代理到您的 nodejs 应用程序。您可以设置 nginx 来处理 ssl 请求,并且只对您的节点 app.js 说 http。
EDIT TO ADD (4/6/2015)
编辑添加 (4/6/2015)
For systems on using AWS, you are better off using EC2 Elastic Load Balancers to handle SSL Termination, and allow regular HTTP traffic to your EC2 web servers. For further security, setup your security group such that only the ELB is allowed to send HTTP traffic to the EC2 instances, which will prevent external unencrypted HTTP traffic from hitting your machines.
对于使用 AWS 的系统,您最好使用 EC2 弹性负载均衡器来处理 SSL 终止,并允许常规 HTTP 流量到您的 EC2 Web 服务器。为了进一步安全,请设置您的安全组,以便只允许 ELB 将 HTTP 流量发送到 EC2 实例,这将防止外部未加密的 HTTP 流量访问您的机器。
回答by codename-
In express.js (since version 3) you should use that syntax:
在 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);
In that way you provide express middleware to the native http/https server
通过这种方式,您可以向本机 http/https 服务器提供快速中间件
If you want your app running on ports below 1024, you will need to use sudocommand (not recommended) or use a reverse proxy (e.g. nginx, haproxy).
如果您希望您的应用程序在 1024 以下的端口上运行,您将需要使用sudo命令(不推荐)或使用反向代理(例如 nginx、haproxy)。
回答by Dere Sagar
First, you need to create selfsigned.keyand selfsigned.crtfiles. Go to Create a Self-Signed SSL CertificateOr do following steps.
首先,您需要创建selfsigned.key和selfsigned.crt文件。转到创建自签名 SSL 证书或执行以下步骤。
Go to the terminal and run the following command.
转到终端并运行以下命令。
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./selfsigned.key -out selfsigned.crt
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./selfsigned.key -out selfsigned.crt
- After that put the following information
- Country Name (2 letter code) [AU]: US
- State or Province Name (full name) [Some-State]: NY
- Locality Name (eg, city) []:NY
- Organization Name (eg, company) [Internet Widgits Pty Ltd]: xyz (Your - Organization)
- Organizational Unit Name (eg, section) []: xyz (Your Unit Name)
- Common Name (e.g. server FQDN or YOUR name) []: www.xyz.com (Your URL)
- Email Address []: Your email
- 之后输入以下信息
- 国家/地区名称(2 个字母代码)[AU]:美国
- 州或省名称(全名)[Some-State]:NY
- 地点名称(例如,城市)[]:纽约
- 组织名称(例如,公司)[Internet Widgits Pty Ltd]:xyz(您的 - 组织)
- 组织单位名称(例如,部分)[]:xyz(您的单位名称)
- 通用名称(例如服务器 FQDN 或您的姓名)[]:www.xyz.com(您的 URL)
- 电子邮件地址 []:您的电子邮件
After creation adds key & cert file in your code, and pass the options to the server.
创建后在您的代码中添加密钥和证书文件,并将选项传递给服务器。
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)
});
- Finally run your application using https.
- 最后使用https运行您的应用程序。
More information https://github.com/sagardere/set-up-SSL-in-nodejs
回答by eomoto
I ran into a similar issue with getting SSL to work on a port other than port 443. In my case I had a bundle certificate as well as a certificate and a key. The bundle certificate is a file that holds multiple certificates, node requires that you break those certificates into separate elements of an array.
我在让 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/")
});
In app.js you need to specify https and create the server accordingly. Also, make sure that the port you're trying to use is actually allowing inbound traffic.
在 app.js 中,您需要指定 https 并相应地创建服务器。此外,请确保您尝试使用的端口实际上允许入站流量。
回答by Nishchit Dhanani
Including Points:
包括积分:
- SSL setup
- In config/local.js
- In config/env/production.js
- SSL设置
- 在 config/local.js
- 在 config/env/production.js
HTTP and WS handling
HTTP 和 WS 处理
- The app must run on HTTP in development so we can easily debug our app.
- The app must run on HTTPS in production for security concern.
- App production HTTP request should always redirect to https.
- 该应用程序在开发中必须在 HTTP 上运行,以便我们可以轻松调试我们的应用程序。
- 出于安全考虑,该应用程序必须在生产中在 HTTPS 上运行。
- 应用程序生产 HTTP 请求应始终重定向到 https。
SSL configuration
SSL 配置
In Sailsjs there are two ways to configure all the stuff, first is to configure in config folder with each one has their separate files (like database connection regarding settings lies within connections.js ). And second is configure on environment base file structure, each environment files presents in config/envfolder and each file contains settings for particular env.
在 Sailsjs 中,有两种方法可以配置所有东西,第一种是在 config 文件夹中进行配置,每个文件都有自己的单独文件(例如关于设置的数据库连接位于 connection.js 中)。其次是在环境基础文件结构上进行配置,每个环境文件都存在于config/env文件夹中,每个文件都包含特定环境的设置。
Sails first looks in config/env folder and then look forward to config/ *.js
Sails 先在 config/env 文件夹中查找,然后再查找 config/ *.js
Now lets setup ssl in config/local.js.
现在让我们在config/local.js.
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;
Alternative you can add this in config/env/production.jstoo. (This snippet also show how to handle multiple CARoot certi)
或者,您也可以在config/env/production.js 中添加它。(此代码段还显示了如何处理多个 CARoot 证书)
Or in production.js
或者在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 redirection
http/https & ws/wss 重定向
Here ws is Web Socket and wss represent Secure Web Socket, as we set up ssl then now http and ws both requests become secure and transform to https and wss respectively.
这里 ws 是 Web Socket,wss 代表 Secure Web Socket,因为我们设置了 ssl 然后现在 http 和 ws 两个请求都变得安全并分别转换为 https 和 wss。
There are many source from our app will receive request like any blog post, social media post but our server runs only on https so when any request come from http it gives “This site can't be reached” error in client browser. And we loss our website traffic. So we must redirect http request to https, same rules allow for websocket otherwise socket will fails.
我们的应用程序有许多来源会像任何博客文章、社交媒体文章一样收到请求,但我们的服务器仅在 https 上运行,因此当任何来自 http 的请求时,它会在客户端浏览器中显示“无法访问此站点”错误。我们失去了网站流量。所以我们必须将 http 请求重定向到 https,同样的规则允许 websocket 否则套接字将失败。
So we need to run same server on port 80 (http), and divert all request to port 443(https). Sails first compile config/bootstrap.js file before lifting server. Here we can start our express server on port 80.
所以我们需要在端口 80 (http) 上运行相同的服务器,并将所有请求转移到端口 443(https)。Sails 在提升服务器之前首先编译 config/bootstrap.js 文件。在这里,我们可以在端口 80 上启动我们的 Express 服务器。
In config/bootstrap.js (Create http server and redirect all request to https)
在 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();
};
Now you can visit http://www.yourdomain.com, it will redirect to https://www.yourdomain.com
现在您可以访问http://www.yourdomain.com,它将重定向到https://www.yourdomain.com
回答by CoolAJ86
Use greenlock-express: Free SSL, Automated HTTPS
使用 greenlock-express:免费 SSL,自动 HTTPS
Greenlockhandles certificate issuance and renewal (via Let's Encrypt) and http => https redirection, out-of-the box.
Greenlock处理证书颁发和续订(通过 Let's Encrypt)和 http => https 重定向,开箱即用。
express-app.js:
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:
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: '[email protected]'
, 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);
Screencast
截屏
Watch the QuickStart demonstration: https://youtu.be/e8vaR4CEZ5s
观看快速入门演示:https: //youtu.be/e8vaR4CEZ5s
For Localhost
对于本地主机
Just answering this ahead-of-time because it's a common follow-up question:
提前回答这个问题,因为这是一个常见的后续问题:
You can't have SSL certificates on localhost. However, you can use something like Telebitwhich will allow you to run local apps as real ones.
您不能在本地主机上拥有 SSL 证书。但是,您可以使用Telebit 之类的东西,它允许您像真实应用程序一样运行本地应用程序。
You can also use private domains with Greenlock via DNS-01 challenges, which is mentioned in the README along with various plugins which support it.
您还可以通过 DNS-01 挑战将私有域与 Greenlock 一起使用,自述文件以及支持它的各种插件中提到了这一点。
Non-standard Ports (i.e. no 80 / 443)
非标准端口(即没有 80 / 443)
Read the note above about localhost - you can't use non-standard ports with Let's Encrypt either.
阅读上面关于 localhost 的说明 - 您也不能在 Let's Encrypt 中使用非标准端口。
However, you can expose your internal non-standard ports as external standard ports via port-forward, sni-route, or use something like Telebit that does SNI-routing and port-forwarding / relaying for you.
但是,您可以通过端口转发、sni-route 将内部非标准端口公开为外部标准端口,或者使用 Telebit 之类的工具为您执行 SNI 路由和端口转发/中继。
You can also use DNS-01 challenges in which case you won't need to expose ports at all and you can also secure domains on private networks this way.
您还可以使用 DNS-01 挑战,在这种情况下,您根本不需要公开端口,并且您还可以通过这种方式保护私有网络上的域。
回答by shantanu Chandra
This is how its working for me. The redirection used will redirect all the normal http as well.
这就是它对我的工作方式。使用的重定向也会重定向所有正常的 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);
回答by hoogw
This is my working codefor express 4.0.
这是我的express 4.0工作代码。
express 4.0 is very different from 3.0 and others.
express 4.0 与 3.0 和其他版本有很大不同。
4.0 you have /bin/www file, which you are going to add https here.
4.0 你有 /bin/www 文件,你将在这里添加 https。
"npm start" is standard way you start express 4.0 server.
“npm start”是启动 express 4.0 服务器的标准方式。
readFileSync() function should use __dirnameget current directory
readFileSync() 函数应该使用__dirname获取当前目录
while require() use ./refer to current directory.
而 require()使用 ./指的是当前目录。
First you put private.key and public.cert file under /bin folder, It is same folder as WWW file.
首先你把private.key 和public.cert 文件放在/bin 文件夹下,它和WWW 文件是同一个文件夹。


