Aktivieren von HTTPS in express.js

408

Ich versuche, HTTPS für Express.js für Node zum Laufen zu bringen, und ich kann es nicht herausfinden.

Das ist mein app.jsCode.

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

Wenn ich es ausführe, scheint es nur auf HTTP-Anfragen zu antworten.

Ich habe eine einfache Vanille- node.jsbasierte HTTPS-App geschrieben:

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

Und wenn ich diese App laufen, es tut reagieren auf HTTPS - Anfragen. Beachten Sie, dass ich nicht denke, dass toString () für das fs-Ergebnis von Bedeutung ist, da ich Kombinationen von beiden verwendet habe und immer noch kein es bueno.


BEARBEITEN ZUM HINZUFÜGEN:

Für Produktionssysteme ist es wahrscheinlich besser, Nginx oder HAProxy zu verwenden, um Anforderungen an Ihre nodejs-App zu senden. Sie können nginx so einrichten, dass es die SSL-Anforderungen verarbeitet, und einfach http mit Ihrem Knoten app.js sprechen.

BEARBEITEN ZUM HINZUFÜGEN (06.04.2015)

Für Systeme, die AWS verwenden, ist es besser, EC2 Elastic Load Balancers zu verwenden, um die SSL-Beendigung zu handhaben und regelmäßigen HTTP-Verkehr zu Ihren EC2-Webservern zuzulassen. Richten Sie Ihre Sicherheitsgruppe für weitere Sicherheit so ein, dass nur die ELB HTTP-Verkehr an die EC2-Instanzen senden darf, um zu verhindern, dass externer unverschlüsselter HTTP-Verkehr auf Ihre Computer gelangt.


Alan
quelle
3
Hier kurz und bündig beantwortet: stackoverflow.com/a/23894573/1882064
arcseldon
Zum letzten Kommentar zu AWS: Muss mit dem https-Modul kein Server erstellt werden? Meine Zertifikate werden über Jenkins in AWS hochgeladen und mit ARN verarbeitet. Ich habe keine Dateipfade zu verwenden (in https-Optionen)
sqldoug
@sqldoug Ich bin nicht sicher, ob ich die Frage verstehe. AWS-ELBs können so konfiguriert werden, dass sie HTTPS-Verbindungen akzeptieren und als SSL-Endpunkt fungieren. Das heißt, sie sprechen über reguläres HTTP mit Ihren App-Servern. Es gibt normalerweise keinen Grund, warum nodejs sich mit SSL befassen, da es sich nur um zusätzlichen Verarbeitungsaufwand handelt, der entweder auf ELB-Ebene oder auf HTTP-Proxy-Ebene im Stack verarbeitet werden kann.
Alan
Danke Alan; Ja, ich habe inzwischen festgestellt, dass Node sich nicht mit SSL befassen muss, wenn AWS ELBs so konfiguriert werden können.
sqldoug

Antworten:

672

In express.js (seit Version 3) sollten Sie diese Syntax verwenden:

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

Auf diese Weise stellen Sie dem nativen http / https-Server Express-Middleware zur Verfügung

Wenn Ihre App auf Ports unter 1024 ausgeführt werden soll, müssen Sie den sudoBefehl (nicht empfohlen) oder einen Reverse-Proxy (z. B. nginx, haproxy) verwenden.

Code Name-
quelle
2
Alles ist hier geschrieben: github.com/visionmedia/express/wiki/Migrating-from-2.x-to-3.x Ziffer Anwendungsfunktion
codename-
74
Beachten Sie, dass 443 zwar der Standardport für HTTPS ist, Sie jedoch während der Entwicklung wahrscheinlich 8443 verwenden möchten, da die meisten Systeme keine Nicht-Root-Listener an Ports mit niedriger Nummer zulassen.
Ebohlman
1
Mann, es funktioniert wie Magie :) Es akzeptiert auch .pem-Dateien, so wie es auch sein sollte
Marcelo Teixeira Ruggeri
5
Express 4 es funktioniert nicht, es funktioniert, localhost:80aber nichthttps://localhost:443
Muhammad Umer
13
Wenn Sie Nginx für Reverse Proxy verwenden möchten, kann dies die SSL-Zertifikate für Sie anstelle des Knotens verarbeiten
Gianfranco P.
48

Zunächst müssen Sie die Dateien selfsigned.key und selfsigned.crt erstellen. Gehen Sie zu Erstellen eines selbstsignierten SSL-Zertifikats oder führen Sie die folgenden Schritte aus.

Gehen Sie zum Terminal und führen Sie den folgenden Befehl aus.

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./selfsigned.key -out selfsigned.crt

  • Geben Sie danach die folgenden Informationen ein
  • Ländername (2-Buchstaben-Code) [AU]: US
  • Name des Bundesstaates oder der Provinz (vollständiger Name) [Some-State]: NY
  • Ortsname (z. B. Stadt) []: NY
  • Name der Organisation (z. B. Firma) [Internet Widgits Pty Ltd]: xyz (Ihre - Organisation)
  • Name der Organisationseinheit (z. B. Abschnitt) []: xyz (Name Ihrer Einheit)
  • Allgemeiner Name (z. B. FQDN des Servers oder IHR Name) []: www.xyz.com (Ihre URL)
  • E-Mail-Adresse []: Ihre E-Mail

Fügen Sie nach der Erstellung eine Schlüssel- und Zertifizierungsdatei in Ihren Code ein und übergeben Sie die Optionen an den 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)
});
  • Führen Sie Ihre Anwendung schließlich mit https aus .

Weitere Informationen unter https://github.com/sagardere/set-up-SSL-in-nodejs

Dere Sagar
quelle
Von der Verwendung von Sudo sollte abgeraten werden, sofern dies nicht erforderlich ist. Ich habe diesen Vorgang gerade ohne sudo durchlaufen, war aber als Administrator auf dem Computer angemeldet.
Jhickok
27

Ich hatte ein ähnliches Problem damit, dass SSL an einem anderen Port als Port 443 funktioniert. In meinem Fall hatte ich ein Bundle-Zertifikat sowie ein Zertifikat und einen Schlüssel. Das Bundle-Zertifikat ist eine Datei, die mehrere Zertifikate enthält. Der Knoten erfordert, dass Sie diese Zertifikate in separate Elemente eines Arrays aufteilen.

    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 müssen Sie https angeben und den Server entsprechend erstellen. Stellen Sie außerdem sicher, dass der Port, den Sie verwenden möchten, tatsächlich eingehenden Datenverkehr zulässt.

eomoto
quelle
Ich habe einen Schlüssel und ein gebündeltes Zertifikat. Ich bin mir nicht sicher, welches Zertifikat: fs.readFileSync (PATH_TO_CERT) wäre und wie man das gebündelte Zertifikat "bricht". Es gibt mehr als 20 Schlüssel im Zertifikat, wenn Sie mich fragen :)
Muhammad Umar
@ MuhammadUmar Sie müssen das Bündel nicht brechen oder sogar angeben, wenn Sie keines haben, Sie werden ein Bündel-Zertifikat haben, falls zutreffend, und Zertifikat (öffentlicher Schlüssel) und Schlüssel (privater Schlüssel)
Hayden Thring
@eomoto danke Kumpel! Das ist das Beste, du hast das Beispiel, das ich brauchte, total genagelt
Hayden Thring
11

Einschließlich Punkte:

  1. SSL-Setup
    1. In config / local.js
    2. In config / env / Production.js

HTTP- und WS-Behandlung

  1. Die App muss in der Entwicklung auf HTTP ausgeführt werden, damit wir unsere App problemlos debuggen können.
  2. Die App muss aus Sicherheitsgründen in der Produktion auf HTTPS ausgeführt werden.
  3. Die HTTP-Anforderung für die App-Produktion sollte immer zu https umleiten.

SSL-Konfiguration

In Sailsjs gibt es zwei Möglichkeiten, das gesamte Material zu konfigurieren. Die erste besteht darin, im Konfigurationsordner zu konfigurieren, wobei jede Datei ihre eigenen Dateien hat (wie die Datenbankverbindung bezüglich der Einstellungen in connection.js). Und zweitens wird die Struktur der Umgebungsbasisdatei konfiguriert, wobei jede Umgebungsdatei im config/envOrdner angezeigt wird und jede Datei Einstellungen für eine bestimmte Umgebung enthält.

Sails sucht zuerst im Ordner config / env und freut sich dann auf config / * .js

Jetzt können Sie ssl einrichten 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;

Alternativ können Sie dies auch in config / env / Production.js hinzufügen . (Dieses Snippet zeigt auch, wie mit mehreren CARoot-Zertifikaten umgegangen wird.)

Oder in der Produktion.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-Umleitung

Hier ist ws Web Socket und wss steht für Secure Web Socket, da wir ssl und jetzt http einrichten und beide Anforderungen sicher werden und sich in https bzw. wss umwandeln.

Es gibt viele Quellen aus unserer App, die Anfragen erhalten, wie z. B. Blog-Posts und Social-Media-Posts. Unser Server wird jedoch nur unter https ausgeführt. Wenn also Anfragen von http kommen, wird im Client-Browser der Fehler "Diese Site kann nicht erreicht werden" angezeigt. Und wir verlieren unseren Website-Verkehr. Wir müssen also die http-Anfrage an https umleiten. Dieselben Regeln erlauben Websocket, sonst schlägt Socket fehl.

Wir müssen also denselben Server auf Port 80 (http) ausführen und alle Anforderungen an Port 443 (https) umleiten. Sails kompiliert zuerst die Datei config / bootstrap.js, bevor der Server angehoben wird. Hier können wir unseren Express-Server an Port 80 starten.

In config / bootstrap.js (http-Server erstellen und alle Anfragen an https umleiten)

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();
};

Jetzt können Sie http://www.yourdomain.com besuchen . Es wird zu https://www.yourdomain.com weitergeleitet

Nishchit Dhanani
quelle
8

Verwenden Sie Greenlock-Express: Kostenloses SSL, automatisiertes HTTPS

Greenlock übernimmt die sofortige Ausgabe und Erneuerung von Zertifikaten (über Let's Encrypt) und die Umleitung von 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: '[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

Sehen Sie sich die QuickStart-Demonstration an: https://youtu.be/e8vaR4CEZ5s

Für Localhost

Beantworten Sie dies nur im Voraus, da es sich um eine häufige Folgefrage handelt:

Sie können keine SSL-Zertifikate auf localhost haben. Sie können jedoch so etwas wie Telebit verwenden, mit dem Sie lokale Apps als echte Apps ausführen können.

Sie können auch private Domains mit Greenlock über DNS-01-Herausforderungen verwenden, die in der README zusammen mit verschiedenen Plugins, die dies unterstützen, erwähnt werden.

Nicht standardmäßige Ports (dh Nr. 80/443)

Lesen Sie den obigen Hinweis zu localhost. Mit Let's Encrypt können Sie auch keine nicht standardmäßigen Ports verwenden.

Sie können Ihre internen Nicht-Standard-Ports jedoch als externe Standard-Ports über Port-Forward, Sni-Route oder Telebit bereitstellen, das SNI-Routing und Port-Forwarding / Relaying für Sie übernimmt.

Sie können auch DNS-01-Herausforderungen verwenden. In diesem Fall müssen Sie überhaupt keine Ports verfügbar machen, und Sie können auf diese Weise auch Domänen in privaten Netzwerken sichern.

CoolAJ86
quelle
"Sie können keine SSL-Zertifikate auf localhost haben." - Ich habe SSL in meiner React-App auf localhost. Kam hierher und suchte nach Möglichkeiten, wie es in Express funktioniert. React ist mein Frontend und Express ist mein Backend. Muss für Stripe funktionieren, da mein Beitrag zu Stripe in SSL sein muss. Sollte offensichtlich sein, aber in localhost teste ich und auf dem Server wird es Produktion sein.
Taersious
Korrektur: "Sie können keine gültigen SSL-Zertifikate auf localhost haben".
CoolAJ86
6

So funktioniert es bei mir. Die verwendete Umleitung leitet auch alle normalen http um.

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);
Shantanu Chandra
quelle
0

Dies ist mein Arbeitscode für Express 4.0 .

Express 4.0 unterscheidet sich stark von 3.0 und anderen.

4.0 Sie haben die Datei / bin / www, die Sie hier https hinzufügen werden.

"npm start" ist die Standardmethode zum Starten des Express 4.0-Servers.

Die Funktion readFileSync () sollte __dirname get current directory verwenden

while require () benutze ./ verweise auf das aktuelle Verzeichnis.

Zuerst legen Sie die Dateien private.key und public.cert unter dem Ordner / bin ab. Dies ist derselbe Ordner wie die WWW-Datei .

hoogw
quelle