Увімкнення HTTPS на express.js


408

Я намагаюся змусити 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 запити. Зауважте, що я не думаю, що toString () у результаті fs має значення, оскільки я використовував комбінації обох, і досі немає es bueno.


РЕДАКТУЙТЕ ДОДАТИ:

У виробничих системах вам, мабуть, краще використовувати Nginx або HAProxy для проксі-запитів до вашої програми nodejs. Ви можете налаштувати nginx для обробки запитів ssl і просто поговорити http зі своїм вузлом app.js.

РЕДАКТУЙТЕ ДО ДОДАТИ (06.06.2015)

Для систем із використанням AWS вам краще використовувати EC2 Elastic Load Balanceers для обробки SSL-припинення та дозволити регулярний трафік HTTP на ваші веб-сервери EC2. Для подальшої безпеки налаштуйте свою групу безпеки таким чином, щоб лише ELB було дозволено надсилати трафік HTTP до екземплярів EC2, що запобіжить потраплянню зовнішнього незашифрованого HTTP-трафіку на ваші машини.



3
Відповів лаконічно тут: stackoverflow.com/a/23894573/1882064
arcseldon

Щодо останнього коментаря до AWS: чи не потрібно сервер створювати за допомогою модуля https? Мої сертифікати завантажуються в AWS через Jenkins і обробляються з ARN; У мене немає файлових шляхів для використання (в опціях https)
sqldoug

@sqldoug Я не впевнений, що розумію питання. AWS ELB можуть бути налаштовані приймати HTTPS-з'єднання та виступати в якості точки завершення SSL. Тобто вони розмовляють із вашими серверами додатків через звичайний HTTP. Зазвичай nodejs не має справи з SSL, оскільки це просто додаткова обробка даних, яка може обробляти стек на рівні ELB або на рівні HTTP Proxy.
Алан

Спасибі Алан; Так, я з тих пір зрозумів, що Node не потрібно мати справу з SSL, коли AWS ELB можна налаштувати так.
sqldoug

Відповіді:


672

У 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).


2
Все написано тут: github.com/visionmedia/express/wiki/Migrating-from-2.x-to-3.x Пункт функції програми
codename-

74
Зауважте, що хоча 443 є портом за замовчуванням для HTTPS, під час розробки, ймовірно, ви хочете використовувати щось на зразок 8443, оскільки більшість систем не дозволяють слухачам, котрі не користуються коренем, на портах з низьким номером.
ebohlman

1
Людина, це працює як магія :) Він також приймає файли .pem, як і все одно
Марсело Тейшейра Руджері

5
Експрес 4 це не працює, він працює, localhost:80але ніhttps://localhost:443
Мухаммед Умер

13
якщо ви збираєтесь використовувати nginx для зворотного проксі-сервера, який може обробляти сервіси ssl замість вузла
Gianfranco P.

48

Спочатку потрібно створити файли selfsigned.key та selfsigned.crt . Перейдіть до створення самопідписаного сертифіката SSL Або виконайте наступні дії.

Перейдіть до терміналу і запустіть наступну команду.

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

  • Після цього поставте наступну інформацію
  • Назва країни (2 буквений код) [AU]: США
  • Назва штату чи провінції (повна назва) [Деякі держави]: NY
  • Назва місцевості (наприклад, місто) []: NY
  • Назва організації (наприклад, компанія) [Internet Widgits Pty Ltd]: xyz (Ваша - організація)
  • Назва організаційного підрозділу (наприклад, розділ) []: xyz (Ваше ім'я одиниці)
  • Загальна назва (наприклад, FQDN сервера або ВАШЕ ім'я) []: www.xyz.com (Ваша URL-адреса)
  • Адреса електронної пошти []: Ваш електронний лист

Після створення додайте у свій код файл key & 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


Використовувати судо слід не рекомендувати, якщо не потрібно. Я просто пройшов цей процес, не використовуючи sudo, але мене зареєстрували як адміністратор на машині.
jhickok

27

Я зіткнувся з подібною проблемою з тим, щоб 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 та створити сервер відповідно. Також переконайтесь, що порт, який ви намагаєтеся використовувати, насправді дозволяє вхідний трафік.


у мене є ключ і пакетний cert, я не впевнений, що це cert: fs.readFileSync (PATH_TO_CERT), який би був і як "зламати" пакетний cert, є 20+ клавіш у cert, якщо ви запитаєте мене :)
Мухаммад Умар

@MuhammadUmar вам не доведеться розбивати пакет або навіть вказати його, якщо у вас його немає, у вас буде церт пакетів, якщо це можливо, і cert (відкритий ключ) і ключ (приватний ключ)
Hayden Thring

@eomoto спасибі! це найкраще, ви повністю прибили приклад, який мені потрібен
Хайден Thring

11

Включаючи бали:

  1. Налаштування SSL
    1. У config / local.js
    2. У config / env / production.js

Обробка HTTP та WS

  1. Додаток повинен працювати на HTTP у розробці, щоб ми могли легко налагодити наш додаток.
  2. Додаток повинен працювати на HTTPS у виробництві з метою безпеки.
  3. HTTP-запит на виробництво додатків завжди повинен перенаправляти на https.

Конфігурація SSL

У Sailsjs є два способи налаштувати всі речі, спочатку - налаштувати в папці config кожен з яких має свої окремі файли (наприклад, підключення до бази даних щодо налаштувань лежить в межах Links.js). А друге - це налаштування на структурі базового файлу середовища, кожен файл середовища представлений у config/envпапці, і кожен файл містить налаштування для конкретної env.

Вітрила спочатку шукає у папці config / env, а потім сподівається на config / * .js

Тепер давайте налаштування ssl в 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;

Альтернативно, ви можете додати це також у 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, інакше сокет вийде з ладу.

Тому нам потрібно запустити один і той же сервер на порт 80 (http) і переадресувати весь запит на порт 443 (https). Вітрила спочатку компілюють файл 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


8

Використовуйте 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);

Екранна трансляція

Дивіться демонстрацію QuickStart: https://youtu.be/e8vaR4CEZ5s

Для Localhost

Просто відповіді на це заздалегідь, тому що це поширене подальше запитання:

Ви не можете мати сертифікати SSL на localhost. Однак ви можете використовувати щось на кшталт Telebit, що дозволить запускати локальні додатки як справжні.

Ви також можете використовувати приватні домени з Greenlock через виклики DNS-01, що згадується в README разом з різними плагінами, які його підтримують.

Нестандартні порти (тобто немає 80/443)

Прочитайте вище примітку про localhost - ви не можете використовувати нестандартні порти і з Let's Encrypt.

Однак ви можете виставити свої внутрішні нестандартні порти як зовнішні стандартні порти через переадресацію порту, сні-маршрут або використовувати щось на кшталт Telebit, що робить маршрутизацію SNI та переадресацію / ретрансляцію для вас.

Ви також можете використовувати виклики DNS-01, і в цьому випадку вам не потрібно буде відкривати порти, і ви також можете захистити домени в приватних мережах таким чином.


"Ви не можете мати сертифікати SSL на localhost." - У мене SSL працює над моїм додатком React на localhost. Сюди прийшли шукати, як змусити його працювати в Express. React - це мій фронтенд, а Express - мій вихідний. Потрібно, щоб він працював на Stripe, оскільки мій пост у Stripe повинен бути в SSL. Має бути очевидним, але в localhost я тестую, а на сервері це буде виробництво.
Taersious

Виправлення: "Ви не можете мати дійсні сертифікати SSL на localhost".
CoolAJ86

6

Ось як це працює для мене. Використовуване перенаправлення також переспрямовує всі звичайні 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);

0

Це мій робочий код для експрес 4.0 .

express 4.0 сильно відрізняється від 3.0 та інших.

4.0 у вас є / bin / www файл, який ви збираєтеся тут додати https.

"npm start" - це стандартний спосіб запуску сервера Express 4.0.

Функція readFileSync () повинна використовувати __dirname отримати поточний каталог

при цьому вимагайте () використання ./ зверніться до поточного каталогу.

Спочатку ви поміщаєте файл private.key та public.cert в папку / bin, це та сама папка, що і файл WWW .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.