redirect - heroku https
Heroku NodeJS http a https ssl redirigido forzado (11)
Tengo una aplicación ejecutándose en heroku con express en el nodo con https ,. ¿Cómo identifico el protocolo para forzar una redirección a https con nodejs en heroku?
Mi aplicación es solo un simple servidor http, no (todavía) se da cuenta de que heroku lo está enviando solicitudes https:
/* Heroku provides the port they want you on in this environment variable (hint: it''s not 80) */
app.listen(process.env.PORT || 3000);
A partir de hoy, 10 de octubre de 2014 , usando Heroku Cedar stack , y ExpressJS ~ 3.4.4 , aquí hay un conjunto de códigos de trabajo.
Lo principal que hay que recordar aquí es que estamos desplegando a Heroku. La terminación SSL ocurre en el equilibrador de carga, antes de que el tráfico cifrado llegue a la aplicación de su nodo. Es posible comprobar si https se utilizó para realizar la solicitud con req.headers [''x-forward-proto''] === ''https'' .
No es necesario que nos preocupemos por tener certificados SSL locales dentro de la aplicación, etc., como lo haría si estuviera alojado en otros entornos. Sin embargo, debe obtener un complemento SSL aplicado a través de Complementos Heroku primero si usa su propio certificado, subdominios, etc.
A continuación, solo agregue lo siguiente para hacer la redirección desde cualquier otra cosa que no sea HTTPS a HTTPS. Esto está muy cerca de la respuesta aceptada anteriormente, pero:
- Garantiza el uso de "app.use" (para todas las acciones, no solo para obtener)
- Explota explícitamente la lógica de forceSsl en una función declarada
- No usa ''*'' con "app.use" - esto realmente falló cuando lo probé.
- Aquí, solo quiero SSL en producción. (Cambie según sus necesidades)
Código:
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...
}
Nota para los usuarios de SailsJS (0.10.x). Simplemente puede crear una política (enforceSsl.js) dentro de api / policies:
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();
}
};
A continuación, haga referencia a config / policies.js junto con otras políticas, por ejemplo:
''*'': [''authenticated'', ''enforceSsl'']
Deberías echarle un vistazo a heroku-ssl-redirect . ¡Funciona a las mil maravillas!
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);
He escrito un módulo de nodo pequeño que aplica SSL en proyectos express. Funciona tanto en situaciones estándar como en el caso de proxies inversos (Heroku, nodejitsu, etc.)
La respuesta aceptada tiene un dominio codificado, lo que no es demasiado bueno si tiene el mismo código en varios dominios (por ejemplo: dev-yourapp.com, test-yourapp.com, yourapp.com).
Use esto en su lugar:
/* 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/
La respuesta es usar el encabezado de ''x-forward-proto'' que Heroku pasa al frente, ya que es proxy thingamabob. (nota al margen: también pasan otras muchas variables x que pueden ser útiles, compruébalo ).
Mi código:
/* 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 */
})
Gracias Brandon, estaba esperando ese retraso de 6 horas que no me dejaba responder mi propia pregunta.
Los usuarios de Loopback pueden usar una versión ligeramente adaptada de la respuesta de Arcseldon como middleware:
servidor / 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());
Si desea probar el encabezado x-forwarded-proto
en su servidor local, puede usar nginx para configurar un archivo vhost que redireccione todas las solicitudes a su aplicación de nodo. Su archivo de configuración nginx vhost podría verse así
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;
}
}
Los bits importantes aquí son que está transmitiendo todas las solicitudes al puerto localhost 3000 (aquí es donde se ejecuta su aplicación de nodo) y está configurando un grupo de encabezados, incluido X-Forwarded-Proto
Luego, en su aplicación, detecte ese encabezado como de costumbre
Exprimir
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
})
Hospedadores
Finalmente, debes agregar esta línea a tu archivo de hosts
127.0.0.1 dummy.com
Si está utilizando cloudflare.com como CDN en combinación con heroku, puede habilitar la redirección ssl automática dentro de cloudflare fácilmente así:
Inicia sesión y ve a tu tablero de instrumentos
Seleccionar reglas de página
- Agregue su dominio, por ej. Www.example.com y cambie siempre use https para en
Una forma más específica de expresar esto.
app.enable(''trust proxy'');
app.use(''*'', (req, res, next) => {
if (req.secure) {
return next();
}
res.redirect(`https://${req.hostname}${req.url}`);
});
Verificar el protocolo en el encabezado X-Forwarded-Proto funciona bien en Heroku, al igual que Derek ha señalado. Por lo que vale, aquí está una esencia del middleware Express que uso y su prueba correspondiente.
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 */
}
});