Heroku NodeJS http в https ssl принудительное перенаправление - PullRequest
97 голосов
/ 25 августа 2011

У меня есть приложение, запущенное на героку с экспрессом на узле с https. Как мне определить протокол для принудительного перенаправления на https с nodejs на heroku?

Мое приложение - просто простой http-сервер, оно (пока) не осознает, что heroku отправляет ему запросы https:

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

Ответы [ 11 ]

102 голосов
/ 27 мая 2014

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

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

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

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

  1. Гарантирует, что вы используете "app.use" (для всех действий, а не только для получения)
  2. Явно экстернализуетЛогика forceSsl в объявленной функции
  3. Не использует '*' с "app.use" - это на самом деле не удалось, когда я проверял это.
  4. Здесь я хочу только 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).Вы можете просто создать политику (forceceSsl.js) внутри api /icies:

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 /icies.js вместе с любыми другими политиками, например:

'*': ['authenticated', 'forceceSsl']

93 голосов
/ 31 августа 2011

Ответ заключается в том, чтобы использовать заголовок «x-forwarded-proto», который Heroku передает вперед, так как он делает это через посредник. (примечание: они также передают несколько других переменных 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-часовой задержки, которая не позволила бы мне ответить на мой собственный вопрос.

21 голосов
/ 30 марта 2016

Принятый ответ содержит жестко закодированный домен, что не слишком хорошо, если у вас один и тот же код на нескольких доменах (например, 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/

16 голосов
/ 23 марта 2014

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

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

6 голосов
/ 15 марта 2015

Если вы хотите проверить заголовок x-forwarded-proto на вашем локальном хосте, вы можете использовать nginx для настройки файла vhost, который передает все запросы к вашему приложению узла.Ваш конфигурационный файл 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 3000 (здесь работает приложение вашего узла).и вы настраиваете несколько заголовков, включая X-Forwarded-Proto

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

Express

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

Koa

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
4 голосов
/ 18 ноября 2014

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

  1. Войдите и перейдите на свою панель управления

  2. Выберите правила страницы

    Select Page Rules

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

Вам стоит взглянуть на 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);
3 голосов
/ 13 августа 2015

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

server / middleware / 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 / server.js

var forceSSL = require('./middleware/forcessl.js');
app.use(forceSSL());
1 голос
/ 03 августа 2017

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

  app.enable('trust proxy');
  app.use('*', (req, res, next) => {
    if (req.secure) {
      return next();
    }
    res.redirect(`https://${req.hostname}${req.url}`);
  });
0 голосов
/ 01 августа 2017
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 */
  }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...