Mengaktifkan HTTPS di express.js

408

Saya mencoba membuat HTTPS bekerja pada express.js untuk node, dan saya tidak bisa mengetahuinya.

Ini app.jskode saya .

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

Ketika saya menjalankannya, sepertinya hanya menanggapi permintaan HTTP.

Saya menulis node.jsaplikasi HTTPS berbasis vanilla sederhana :

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

Dan ketika saya menjalankan aplikasi ini, itu tidak merespon permintaan HTTPS. Perhatikan bahwa saya tidak berpikir toString () pada hasil fs penting, karena saya telah menggunakan kombinasi keduanya dan masih tidak ada es bueno.


Sunting untuk menambahkan:

Untuk sistem produksi, Anda mungkin lebih baik menggunakan Nginx atau HAProxy untuk permintaan proxy ke aplikasi nodejs Anda. Anda dapat mengatur nginx untuk menangani permintaan ssl dan hanya berbicara http ke app.js. simpul Anda

EDIT TO ADD (4/6/2015)

Untuk sistem yang menggunakan AWS, Anda lebih baik menggunakan EC2 Elastic Load Balancers untuk menangani Termination SSL, dan memungkinkan lalu lintas HTTP reguler ke server web EC2 Anda. Untuk keamanan lebih lanjut, atur grup keamanan Anda sedemikian rupa sehingga hanya ELB yang diizinkan mengirim lalu lintas HTTP ke mesin virtual EC2, yang akan mencegah lalu lintas HTTP tidak terenkripsi eksternal mengenai mesin Anda.


Alan
sumber
3
Dijawab dengan singkat di sini: stackoverflow.com/a/23894573/1882064
arcseldon
Mengenai komentar terakhir tentang AWS: apakah server tidak perlu dibuat dengan modul https? Sertifikat saya diunggah ke AWS melalui Jenkins dan ditangani dengan ARN; Saya tidak memiliki jalur file untuk digunakan (dalam opsi https)
sqldoug
@ sqldoug Saya tidak yakin saya mengerti pertanyaannya. AWS ELBs dapat dikonfigurasi untuk menerima koneksi HTTPS dan bertindak sebagai titik terminasi SSL. Artinya, mereka berbicara ke server aplikasi Anda melalui HTTP biasa. Biasanya tidak ada alasan untuk memiliki nodejs berurusan dengan SSL, karena itu hanya overhead pemrosesan tambahan yang dapat ditangani di tingkat ELB atau di tingkat HTTP Proxy.
Alan
Terima kasih Alan; ya saya telah menyadari bahwa Node tidak perlu berurusan dengan SSL ketika AWS ELBs dapat dikonfigurasi.
sqldoug

Jawaban:

673

Di express.js (sejak versi 3) Anda harus menggunakan sintaks itu:

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

Dengan cara itu Anda memberikan middleware ekspres ke server http / https asli

Jika Anda ingin aplikasi Anda berjalan pada port di bawah 1024, Anda harus menggunakan sudoperintah (tidak disarankan) atau menggunakan proxy terbalik (misalnya nginx, haproxy).

nama kode-
sumber
2
Semua tertulis di sini: github.com/visionmedia/express/wiki/Migrating-from-2.x-to-3.x Fungsi Aplikasi
codename-
74
Perhatikan bahwa meskipun 443 adalah port default untuk HTTPS, selama pengembangan Anda mungkin ingin menggunakan sesuatu seperti 8443 karena sebagian besar sistem tidak mengizinkan pendengar non-root pada port bernomor rendah.
ebohlman
1
Man, ini bekerja seperti sihir :) Ia menerima file .pem juga, dan memang seharusnya
Marcelo Teixeira Ruggeri
5
mengungkapkan 4 itu tidak bekerja, itu bekerja untuk localhost:80tetapi tidakhttps://localhost:443
Muhammad Umer
13
jika Anda akan menggunakan nginx untuk reverse proxy, yang dapat menangani sertifikat ssl untuk Anda alih-alih simpul
Gianfranco P.
48

Pertama, Anda perlu membuat selfsigned.key dan selfsigned.crt file. Pergi ke Buat Sertifikat SSL yang Ditandatangani Sendiri Atau lakukan langkah-langkah berikut.

Pergi ke terminal dan jalankan perintah berikut.

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

  • Setelah itu letakkan informasi berikut
  • Nama Negara (2 kode huruf) [AU]: AS
  • Nama Negara Bagian atau Provinsi (nama lengkap) [Beberapa Negara]: NY
  • Nama Daerah (mis. Kota) []: NY
  • Nama Organisasi (misalnya, perusahaan) [Internet Widgits Pty Ltd]: xyz (Organisasi Anda)
  • Nama Unit Organisasi (misal, bagian) []: xyz (Nama Unit Anda)
  • Nama Umum (mis. Server FQDN atau nama ANDA) []: www.xyz.com (URL Anda)
  • Alamat Email []: Email Anda

Setelah pembuatan, tambahkan file kunci & sertifikat dalam kode Anda, dan berikan opsi ke 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)
});
  • Terakhir jalankan aplikasi Anda menggunakan https .

Informasi lebih lanjut https://github.com/sagardere/set-up-SSL-in-nodejs

Dere Sagar
sumber
Menggunakan sudo harus dicegah kecuali perlu. Saya baru saja melalui proses ini tanpa menggunakan sudo, tetapi saya login sebagai admin di mesin.
jhickok
27

Saya mengalami masalah serupa dengan mendapatkan SSL untuk bekerja pada port selain port 443. Dalam kasus saya, saya memiliki sertifikat bundel serta sertifikat dan kunci. Sertifikat bundel adalah file yang menyimpan beberapa sertifikat, simpul mengharuskan Anda memecah sertifikat tersebut menjadi elemen-elemen terpisah dari array.

    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/")
    });

Di app.js Anda perlu menentukan https dan membuat server yang sesuai. Juga, pastikan bahwa port yang Anda coba gunakan sebenarnya memungkinkan lalu lintas masuk.

eomoto
sumber
saya punya kunci dan sertifikat yang dibundel, saya tidak yakin apa yang pasti: fs.readFileSync (PATH_TO_CERT), akan dan bagaimana "memecahkan" sertifikat yang dibundel, ada seperti 20 kunci dalam sertifikat jika Anda bertanya kepada saya :)
Muhammad Umar
@MuhammadUmar Anda tidak perlu memecahkan bundel atau bahkan menentukannya jika Anda tidak memilikinya, Anda akan memiliki sertifikat bundel jika berlaku, dan cert (kunci publik) dan kunci (kunci pribadi)
Hayden Thring
@ eomoto terima kasih bud! ini adalah yang terbaik, Anda benar-benar menemukan contoh yang saya butuhkan
Hayden Thring
11

Termasuk Poin:

  1. Penyiapan SSL
    1. Di config / local.js
    2. Di config / env / production.js

Penanganan HTTP dan WS

  1. Aplikasi harus dijalankan dengan HTTP yang sedang dikembangkan sehingga kami dapat dengan mudah men-debug aplikasi kami.
  2. Aplikasi harus berjalan pada HTTPS dalam produksi untuk masalah keamanan.
  3. Permintaan HTTP produksi aplikasi harus selalu dialihkan ke https.

Konfigurasi SSL

Dalam Sailsjs ada dua cara untuk mengkonfigurasi semua hal, pertama adalah mengkonfigurasi di folder config dengan masing-masing memiliki file terpisah (seperti koneksi database tentang pengaturan terletak di dalam koneksi.js). Dan yang kedua adalah mengkonfigurasi pada struktur file basis lingkungan, masing-masing file lingkungan menyajikanconfig/env folder dan setiap file berisi pengaturan untuk env tertentu.

Layar pertama terlihat di folder config / env dan kemudian berharap untuk config / * .js

Sekarang mari kita setup ssl in 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;

Alternatif Anda dapat menambahkan ini di config / env / production.js juga. (Cuplikan ini juga menunjukkan cara menangani beberapa sertifikat CARoot)

Atau dalam produksi

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

Di sini ws adalah Web Socket dan wss mewakili Secure Web Socket, karena kami mengatur ssl maka sekarang http dan ws kedua permintaan menjadi aman dan bertransformasi menjadi https dan wss masing-masing.

Ada banyak sumber dari aplikasi kami akan menerima permintaan seperti posting blog, posting media sosial, tetapi server kami hanya berjalan di https sehingga ketika setiap permintaan datang dari http itu memberikan kesalahan "Situs ini tidak dapat dijangkau" di browser klien. Dan kami kehilangan lalu lintas situs web kami. Jadi kita harus mengarahkan permintaan http ke https, aturan yang sama memungkinkan untuk websocket jika tidak maka socket akan gagal.

Jadi kita perlu menjalankan server yang sama pada port 80 (http), dan mengalihkan semua permintaan ke port 443 (https). Berlayar mengkompilasi file config / bootstrap.js terlebih dahulu sebelum mengangkat server. Di sini kita dapat memulai server ekspres pada port 80.

Di config / bootstrap.js (Buat server http dan arahkan semua permintaan ke 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();
};

Sekarang Anda dapat mengunjungi http://www.domainanda.com , itu akan dialihkan ke https://www.domainanda.com

Nishchit Dhanani
sumber
8

Gunakan greenlock-express: SSL Gratis, HTTPS Otomatis

Greenlock menangani penerbitan dan pembaruan sertifikat (melalui Let's Encrypt) dan http => https redirection, out-of-the-box.

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

Tonton demonstrasi QuickStart: https://youtu.be/e8vaR4CEZ5s

Untuk Localhost

Hanya menjawab ini sebelumnya karena ini adalah pertanyaan tindak lanjut yang umum:

Anda tidak dapat memiliki sertifikat SSL di localhost. Namun, Anda dapat menggunakan sesuatu seperti Telebit yang akan memungkinkan Anda menjalankan aplikasi lokal sebagai aplikasi asli.

Anda juga dapat menggunakan domain pribadi dengan Greenlock melalui tantangan DNS-01, yang disebutkan dalam README bersama dengan berbagai plugin yang mendukungnya.

Pelabuhan Non-standar (mis. No 80/443)

Baca catatan di atas tentang localhost - Anda tidak dapat menggunakan port non-standar dengan Let's Encrypt.

Namun, Anda dapat mengekspos port non-standar internal Anda sebagai port standar eksternal melalui port-forward, rute-sni, atau menggunakan sesuatu seperti Telebit yang melakukan routing-SNI dan port-forwarding / relaying untuk Anda.

Anda juga dapat menggunakan tantangan DNS-01 dalam hal ini Anda tidak perlu membuka port sama sekali dan Anda juga dapat mengamankan domain di jaringan pribadi dengan cara ini.

CoolAJ86
sumber
"Anda tidak dapat memiliki sertifikat SSL di localhost." - Saya memiliki SSL yang bekerja pada aplikasi Bereaksi saya di localhost. Datang ke sini mencari cara membuatnya bekerja di Express. Bereaksi adalah frontend saya, dan Express adalah backend saya. Perlu untuk bekerja untuk Stripe, karena posting saya ke Stripe harus dalam SSL. Harus jelas, tetapi di localhost saya sedang menguji, dan pada server itu akan menjadi produksi.
Taersious
Koreksi: "Anda tidak dapat memiliki sertifikat SSL yang valid di localhost".
CoolAJ86
6

Beginilah cara kerjanya untuk saya. Pengalihan yang digunakan akan mengarahkan semua http normal juga.

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
sumber
0

Ini adalah kode kerja saya untuk express 4.0 .

express 4.0 sangat berbeda dari 3.0 dan lainnya.

4.0 Anda memiliki file / bin / www, yang akan Anda tambahkan https di sini.

"npm start" adalah cara standar Anda memulai express 4.0 4.0 server.

Fungsi readFileSync () harus menggunakan __dirname untuk mendapatkan direktori saat ini

sementara membutuhkan () gunakan ./ merujuk ke direktori saat ini.

Pertama Anda meletakkan file private.key dan public.cert di bawah folder / bin, Ini adalah folder yang sama dengan file WWW .

hoogw
sumber