Как заставить SSL / https в Express.js

Я пытаюсь создать промежуточное программное обеспечение для Express.js для перенаправления всего небезопасного (порт 80) трафика на защищенный порт SSL (443). К сожалению, в запросе Express.js нет информации, которая позволяет определить, проходит ли запрос через http или https.

Одним из решений было бы redirect каждого запроса, но это не вариант для меня.

Заметки:

  1. Нет возможности справиться с Apache или чем-то еще. Это нужно сделать в узле.

  2. В приложении может запускаться только один сервер.

Как бы вы это решили?

Хотя вопрос выглядит год назад, я хотел бы ответить, поскольку это могло бы помочь другим. Его действительно просто с последней версией expressjs (2.x). Сначала создайте ключ и сертификат, используя этот код.

openssl genrsa -out ssl-key.pem 1024

$ openssl req -new -key ssl-key.pem -out certrequest.csr .. $ openssl req -new -key ssl-key.pem -out certrequest.csr подсказок

$ openssl x509 -req -in certrequest.csr -signkey ssl-key.pem -out ssl-cert.pem

Храните файлы сертификатов и ключей в папке, содержащей app.js. Затем отредактируйте файл app.js и напишите следующий код перед express.createServer ()

 var https = require('https'); var fs = require('fs'); var sslkey = fs.readFileSync('ssl-key.pem'); var sslcert = fs.readFileSync('ssl-cert.pem') var options = { key: sslkey, cert: sslcert }; 

Теперь передайте объект options в функции createServer ()

 express.createServer(options); 

Готово!

Во-первых, позвольте мне посмотреть, смогу ли я прояснить проблему. Вы ограничены одним (1) процессом node.js, но этот процесс может прослушивать два (2) сетевых порта, как 80, так и 443, верно? (Когда вы говорите один сервер, это неясно, если вы имеете в виду один процесс или только один сетевой порт).

Учитывая это ограничение, вы, кажется, проблема, по причинам, которые вы не предоставляете, каким-то образом ваши клиенты подключаются к неправильному порту. Это причудливый крайний случай, поскольку по умолчанию клиенты будут отправлять HTTP-запросы на порт 80 и HTTPS на порт 443. И когда я говорю «по умолчанию», я имею в виду, если в URL-адреса не указаны определенные порты. Поэтому, если вы явно не используете перекрестные URL-адреса, такие как http://example.com:443 и https://example.com:80 , у вас действительно не должно быть перекрестного трафика, попавшего на ваш сайт. Но так как вы задали вопрос, я думаю, вы его должны иметь, хотя я уверен, вы используете нестандартные порты, а не по умолчанию 80/443.

Итак, для фона: ДА некоторые веб-серверы справляются с этим достаточно хорошо. Например, если вы делаете http://example.com:443 в nginx, он ответит на ответ HTTP 400 «Плохой запрос», указывающий «Простой HTTP-запрос был отправлен на HTTPS-порт». ДА, вы можете прослушивать как 80, так и 443 из одного и того же процесса node.js. Вам просто нужно создать 2 отдельных экземпляра express.createServer() , так что это не проблема. Вот простая программа для демонстрации обработки обоих протоколов.

 var fs = require("fs"); var express = require("express"); var http = express.createServer(); var httpsOptions = { key: fs.readFileSync('key.pem'), cert: fs.readFileSync('cert.pem') }; var https = express.createServer(httpsOptions); http.all('*', function(req, res) { console.log("HTTP: " + req.url); return res.redirect("https://" + req.headers["host"] + req.url); }); http.error(function(error, req, res, next) { return console.log("HTTP error " + error + ", " + req.url); }); https.error(function(error, req, res, next) { return console.log("HTTPS error " + error + ", " + req.url); }); https.all('*', function(req, res) { console.log("HTTPS: " + req.url); return res.send("Hello, World!"); }); http.listen(80); 

И я могу проверить это через cURL следующим образом:

 $ curl --include --silent http://localhost/foo HTTP/1.1 302 Moved Temporarily X-Powered-By: Express Content-Type: text/html Location: https://localhost/foo Connection: keep-alive Transfer-Encoding: chunked 

Moved Temporarily. Redirecting to https://localhost/foo

$ curl --include --silent --insecure https://localhost:443/foo HTTP/1.1 200 OK X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 13 Connection: keep-alive Hello, World!%

И показывая redirect с HTTP на HTTPS …

 curl --include --silent --location --insecure 'http://localhost/foo?bar=bux' HTTP/1.1 302 Moved Temporarily X-Powered-By: Express Content-Type: text/html Location: https://localhost/foo?bar=bux Connection: keep-alive Transfer-Encoding: chunked HTTP/1.1 200 OK X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 13 Connection: keep-alive Hello, World!% 

Таким образом, это будет работать для обслуживания обоих протоколов для обычного случая и перенаправления должным образом. Однако кресты не работают вообще. Я полагаю, что запрос с перекрестными ссылками на express-сервер не будет перенаправляться через стек промежуточного программного обеспечения, поскольку он будет рассматриваться как ошибка с самого начала и даже не сможет правильно обработать URI-запрос, что необходимо для отправьте его через цепочку промежуточного программного обеспечения маршрута. Экспресс-стек даже не получает их, я думаю, потому что они не являются действительными запросами, поэтому они игнорируются где-то в стеке узлов узла. Вероятно, вы можете написать сервер, чтобы сделать это, и там, возможно, уже есть модуль, но вам придется писать его прямо на уровне TCP. И вам придется обнаруживать обычный HTTP-запрос в первом fragmentе данных клиента, который попадает на порт TCP, и подключать это подключение к HTTP-серверу вместо обычного квитирования TLS.

Когда я делаю это, мои явные обработчики ошибок НЕ получают вызов.

 curl --insecure https://localhost:80/foo curl: (35) Unknown SSL protocol error in connection to localhost:80 curl http://localhost:443/foo curl: (52) Empty reply from server 

На всякий случай, если вы размещаете на Heroku и просто хотите перенаправить на HTTPS независимо от порта, вот решение промежуточного программного обеспечения, которое мы используем.

Он не беспокоится о перенаправлении, если вы разрабатываете локально.

 function requireHTTPS(req, res, next) { // The 'x-forwarded-proto' check is for Heroku if (!req.secure && req.get('x-forwarded-proto') !== 'https' && process.env.NODE_ENV !== "development") { return res.redirect('https://' + req.get('host') + req.url); } next(); } 

Вы можете использовать его с Express (2.x и 4.x) так:

 app.use(requireHTTPS); 

На основании ответа Элиаса, но с встроенным кодом. Это работает, если у вас есть узел за nginx или балансировщик нагрузки. Nginx или балансировщик нагрузки всегда будут удалять узел с помощью простого старого http, но он устанавливает заголовок, чтобы вы могли отличить его.

 app.use(function(req, res, next) { var schema = req.headers['x-forwarded-proto']; if (schema === 'https') { // Already https; don't do anything special. next(); } else { // Redirect to https. res.redirect('https://' + req.headers.host + req.url); } }); 

http.createServer (app.handle) .listen (80)

https.createServer (параметры, app.handle) .listen (443)

для express 2x

Этот код выглядит так, как будто он делает то, что вам нужно: https://gist.github.com/903596

Попробуйте этот пример:

 var express = require('express'); var app = express(); // set up a route to redirect http to https app.use(function (req, res, next) { if (!/https/.test(req.protocol)) { res.redirect("https://" + req.headers.host + req.url); } else { return next(); } }); var webServer = app.listen(port, function () { console.log('Listening on port %d', webServer.address().port); }); 

Поскольку я работал над nginx, у меня был доступ к свойству x-forwarded-proto заголовка, поэтому я мог написать крошечное промежуточное программное обеспечение для перенаправления всего трафика, как описано здесь: http://elias.kg/post/14971446990/force-ssl- с-express-JS-на-Heroku-Nginx

Изменить: обновлен URL-адрес

  • Как установить версию TLS на apache HttpClient
  • Решение javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed Ошибка?
  • Отключить SSLv3 в основных браузерах
  • Проблемы с подключением через HTTPS / SSL через собственный клиент Java
  • Как легко создать сертификат SSL и настроить его в Apache2 в Mac OS X?
  • Ошибка SSL: certificate_verify_failed при очистке https://www.thenewboston.com/
  • Как найти версию SSL / TLS в Java
  • ASP.NET MVC RequireHttps только в производстве
  • Какой простой способ полностью игнорировать ssl с java-url-соединениями?
  • Сколько накладных расходов накладывает SSL?
  • Как искать не ssl google?
  • Давайте будем гением компьютера.