在express.js上启用HTTPS

我试图让HTTPS在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请求,只对你的节点app.js说http。

编辑添加(4/6/2015)

对于使用AWS的系统,您最好使用EC2弹性负载均衡器来处理SSL终止,并允许常规HTTP通信到您的EC2 web服务器。为了进一步提高安全性,请设置安全组,以便只允许ELB向EC2实例发送HTTP流量,这将防止外部未加密的HTTP流量攻击您的计算机。


605254 次浏览

在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)。

在让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并相应地创建服务器。另外,确保您尝试使用的端口实际上允许入站流量。

包括点:

    <李> SSL设置
    1. 在config / local.js
    2. 在config / env / production.js
    3. 李< / ol > < / >

    HTTP和WS处理

      应用程序在开发中必须运行在HTTP上,这样我们可以很容易地调试我们的 李应用。< / >
    1. 出于安全考虑,应用程序在生产环境中必须运行在HTTPS上。
    2. 应用程序生产HTTP请求应该始终重定向到https。

    SSL配置

    在Sailsjs中有两种方法来配置所有的东西,首先是在配置文件夹中配置,每个都有各自的文件(比如数据库连接的设置在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;
    

    你也可以在配置/ env / production.js中添加。(这个片段还展示了如何处理多个CARoot certi)

    或者在< em > production.js < / em >

    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套接字,wss代表安全Web套接字,当我们设置ssl时,现在http和ws两个请求都变得安全,并分别转换为https和wss。

    有许多来自我们的应用程序将接收请求,如任何博客文章,社交媒体帖子,但我们的服务器只运行在https上,所以当任何来自http的请求时,它会在客户端浏览器中给出“此站点无法到达”错误。我们失去了网站流量。所以我们必须重定向http请求到https,同样的规则允许websocket,否则socket将失败。

    因此,我们需要在端口80 (http)上运行相同的服务器,并将所有请求转移到端口443(https)。在提升服务器之前,sail首先编译config/bootstrap.js文件。在这里,我们可以在端口80上启动我们的快速服务器。

    在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);

使用greenlock-express:免费SSL,自动HTTPS

Greenlock处理证书颁发和更新(通过Let's Encrypt)和http => https重定向,开箱即用。

# EYZ0:

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;

# EYZ0:

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

< a href = " https://youtu。be/e8vaR4CEZ5s" rel="noreferrer"> ></a> .</p>


<h1>一个主机</h1>


<p>提前回答这个问题,因为这是一个常见的后续问题:</p>


<p>您不能在本地主机上拥有SSL证书。然而,你可以使用像<a href=二进制遥测系统这样的东西,这将允许你运行本地应用程序作为真正的应用程序。

您还可以通过DNS-01挑战使用Greenlock的私有域,这是在README中提到的以及支持它的各种插件。

非标准端口(即不是80 / 443)

阅读上面关于localhost的说明-您也不能使用Let's Encrypt的非标准端口。

但是,您可以通过端口转发、sni-route将内部非标准端口公开为外部标准端口,或者使用像Telebit这样的东西为您进行sni路由和端口转发/中继。

您也可以使用DNS-01挑战,在这种情况下,您根本不需要公开端口,您还可以通过这种方式保护私有网络上的域。

这是我的< em > < / em >工作代码< em > express 4.0 < / em >

Express 4.0与3.0和其他版本有很大不同。

4.0你有/bin/www文件,你要在这里添加HTTPS。

“npm start”是启动express 4.0服务器的标准方式。

readFileSync()函数应该使用< em > __dirname < / em >获取当前目录

while require() 使用< em >。< / em >指向当前目录。

首先你把私有。密钥和公共。“/bin”文件夹下的证书文件 它和WWW文件.

是同一个文件夹
首先,你需要创建selfsigned.keyselfsigned.crt文件。 进入创建自签名SSL证书或执行以下步骤

进入终端,执行如下命令。

# EYZ0

  • 然后输入以下信息
  • 国家名称(2个字母代码)[AU]: 我们
  • 州或省名称(全名)[Some-State]: 纽约
  • 位置名称(例如,城市)[]:纽约
  • 组织名称(如公司)[Internet Widgits Pty Ltd]: xyz(你的-组织)
  • 组织单位名称(如section) []: xyz(你的单位名称)
  • 通用名称(例如服务器FQDN或您的名称)[]:www.xyz.com(您的URL)
  • 电子邮件地址[]:你的电子邮件

创建后添加键&Cert文件,并将选项传递给服务器。

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

不要忘记证书中的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'};

参考< a href = " https://stackoverflow.com/a/54171490/14223224 " > < / >

这个答案与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'

答案在这里:Let's encrypt SSL cannot 't start by &;Error: EACCES: permission denied, open '/etc/letsencrypt/live/domain.net/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

您还可以使用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
}