Heroku NodeJS http to https ssl принудительное перенаправление

У меня есть приложение вверх и работает на heroku с выражением на node с https. Как определить протокол для принудительного перенаправления на https с помощью nodejs на heroku?

Мое приложение - это простой HTTP-сервер, он еще не осознает, что герой отправляет его https-запросы:

/* Heroku provides the port they want you on in this environment variable (hint: it not 80) */
app.listen(process.env.PORT || 3000);

Ответ 1

Ответ заключается в том, чтобы использовать заголовок 'x-forwarded-proto', который Heroku проходит вперед, поскольку он делает это proxy thingamabob. (примечание стороны: они также передают несколько других x-переменных, проверить их).

Мой код:

/* At the top, with other redirect methods before other routes */
app.get('*',function(req,res,next){
  if(req.headers['x-forwarded-proto']!='https')
    res.redirect('https://mypreferreddomain.com'+req.url)
  else
    next() /* Continue to other routes if we're not redirecting */
})

Спасибо Брэндон, просто ждал этой 6-часовой задержки, которая не позволила бы мне ответить на мой собственный вопрос.

Ответ 2

На сегодняшний день 10 октября 2014 года, используя кедровый кедр Heroku и ExpressJS ~ 3.4.4, вот рабочий набор код.

Главное здесь помнить, что мы развертываемся в Heroku. Отключение SSL происходит на балансировщике нагрузки, прежде чем зашифрованный трафик достигнет вашего приложения node. Можно проверить, использовался ли https для запроса с помощью req.headers ['x-forwarded-proto'] === 'https'.

Нам не нужно беспокоиться о наличии локальных сертификатов SSL внутри приложения и т.д., как вы можете, если хостинг в других средах. Однако, если вы используете собственный сертификат, поддомены и т.д., Вы должны получить надстройку SSL, применяемую через надстройки Heroku.

Затем просто добавьте следующее, чтобы сделать перенаправление от чего-либо, кроме HTTPS, до HTTPS. Это очень близко к принятому ответу выше, но:

  • Обеспечивает использование "app.use" (для всех действий, а не только для получения)
  • Явно нарушает логику forceSsl в объявленной функции
  • Не использует '*' с "app.use" - это действительно не сработало, когда я протестировал его.
  • Здесь я хочу только SSL в производстве. (Изменить в соответствии с вашими потребностями)

код:

 var express = require('express'),
   env = process.env.NODE_ENV || 'development';

 var forceSsl = function (req, res, next) {
    if (req.headers['x-forwarded-proto'] !== 'https') {
        return res.redirect(['https://', req.get('Host'), req.url].join(''));
    }
    return next();
 };

 app.configure(function () {

    if (env === 'production') {
        app.use(forceSsl);
    }

    // other configurations etc for express go here...
}

Примечание для пользователей SailsJS (0.10.x). Вы можете просто создать политику (enforceSsl.js) внутри api/политик:

module.exports = function (req, res, next) {
  'use strict';
  if ((req.headers['x-forwarded-proto'] !== 'https') && (process.env.NODE_ENV === 'production')) {
    return res.redirect([
      'https://',
      req.get('Host'),
      req.url
    ].join(''));
  } else {
    next();
  }
};

Затем ссылку из config/policy.js вместе с любыми другими политиками, например:

'*': ['authenticated', 'enforceSsl']

Ответ 3

Принятый ответ имеет в нем жесткий код, что не слишком хорошо, если у вас есть один и тот же код на нескольких доменах (например: dev-yourapp.com, test-yourapp.com, yourapp.com).

Используйте это вместо:

/* Redirect http to https */
app.get('*', function(req,res,next) {
  if(req.headers['x-forwarded-proto'] != 'https' && process.env.NODE_ENV === 'production')
    res.redirect('https://'+req.hostname+req.url)
  else
    next() /* Continue to other routes if we're not redirecting */
});

https://blog.mako.ai/2016/03/30/redirect-http-to-https-on-heroku-and-node-generally/

Ответ 4

Я написал небольшой модуль node, который применяет SSL для экспресс-проектов. Он работает как в стандартных ситуациях, так и в случае обратных прокси (Heroku, nodejitsu и т.д.)

https://github.com/florianheinemann/express-sslify

Ответ 5

Если вы хотите проверить заголовок x-forwarded-proto на своем локальном хосте, вы можете использовать nginx для настройки vhost файл, который проксирует все запросы в ваше приложение node. Ваш конфигурационный файл nginx vhost может выглядеть следующим образом:

Nginx

server {
  listen 80;
  listen 443;

  server_name dummy.com;

  ssl on;
  ssl_certificate     /absolute/path/to/public.pem;
  ssl_certificate_key /absolute/path/to/private.pem;

  access_log /var/log/nginx/dummy-access.log;
  error_log /var/log/nginx/dummy-error.log debug;

  # node
  location / {
    proxy_pass http://127.0.0.1:3000/;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
  }
}

Важными битами здесь являются то, что вы проксируете все запросы на localhost port 3000 (здесь работает ваше приложение node), и вы настраиваете кучу заголовков, включая x-forwarded-proto

Затем в вашем приложении обнаружит этот заголовок как обычно

Экспресс

var app = express()
  .use(function (req, res, next) {
    if (req.header('x-forwarded-proto') == 'http') {
      res.redirect(301, 'https://' + 'dummy.com' + req.url)
      return
    }
    next()
  })

Коа

var app = koa()
app.use(function* (next) {
  if (this.request.headers['x-forwarded-proto'] == 'http') {
    this.response.redirect('https://' + 'dummy.com' + this.request.url)
    return
  }
  yield next
})

Хосты

Наконец, вы должны добавить эту строку в свой hosts файл

127.0.0.1 dummy.com

Ответ 6

Если вы используете cloudflare.com в качестве CDN в сочетании с heroku, вы можете включить автоматическую переадресацию ssl в cloudflare следующим образом:

  • Войдите и перейдите на панель управления

  • Выбор правил страницы

    Select Page Rules

  • Добавьте свой домен, например. www.example.com и переключатель всегда используют https для включения Switch always use https to on

Ответ 7

Пользователи Loopback могут использовать слегка адаптированную версию ответа arcseldon в качестве промежуточного программного обеспечения:

сервер/промежуточный слой /forcessl.js

module.exports = function() {  
  return function forceSSL(req, res, next) {
    var FORCE_HTTPS = process.env.FORCE_HTTPS || false;
      if (req.headers['x-forwarded-proto'] !== 'https' && FORCE_HTTPS) {
        return res.redirect(['https://', req.get('Host'), req.url].join(''));
      }
      next();
    };
 };

сервер/server.js

var forceSSL = require('./middleware/forcessl.js');
app.use(forceSSL());

Ответ 8

Вы должны взглянуть на heroku-ssl-redirect. Он работает как шарм!

var sslRedirect = require('heroku-ssl-redirect');
var express = require('express');
var app = express();

// enable ssl redirect
app.use(sslRedirect());

app.get('/', function(req, res){
  res.send('hello world');
});

app.listen(3000);

Ответ 9

Более конкретный способ сделать это.

  app.enable('trust proxy');
  app.use('*', (req, res, next) => {
    if (req.secure) {
      return next();
    }
    res.redirect(`https://${req.hostname}${req.url}`);
  });

Ответ 10

Проверка протокола в заголовке X-Forwarded-Proto отлично работает на Heroku, как указал Дерек. Для чего это стоит вот суть промежуточного ПО Express, которое я использую, и его соответствующий тест.

Ответ 11

app.all('*',function(req,res,next){
  if(req.headers['x-forwarded-proto']!='https') {
    res.redirect(`https://${req.get('host')}`+req.url);
  } else {
    next(); /* Continue to other routes if we're not redirecting */
  }
});

Ответ 12

С app.use и динамическим URL. У меня работает как на местном, так и на Heroku

app.use(function (req, res, next) {
  if (req.header('x-forwarded-proto') === 'http') {
    res.redirect(301, 'https://' + req.hostname + req.url);
    return
  }
  next()
});