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 следующим образом:
Ответ 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()
});