Heroku NodeJS http a https ssl reindirizzamento forzato

Ho un’applicazione in esecuzione su heroku con express sul nodo con https ,. Come posso identificare il protocollo per forzare un reindirizzamento a https con nodejs su heroku?

La mia app è solo un semplice server http, non è (ancora) conto che heroku le sta inviando richieste 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 partire da oggi, 10 ottobre 2014 , usando lo stack Heroku Cedar e ExpressJS ~ 3.4.4 , ecco un set di codice funzionante.

La cosa principale da ricordare qui è che stiamo schierando su Heroku. La terminazione SSL avviene al servizio di bilanciamento del carico, prima che il traffico crittografato raggiunga l’app del nodo. È ansible verificare se è stato utilizzato https per effettuare la richiesta con req.headers [‘x-forwarded-proto’] === ‘https’ .

Non dobbiamo preoccuparci di avere certificati SSL locali all’interno dell’app ecc. Come potreste fare se ospitiamo in altri ambienti. Tuttavia, è necessario ottenere un add-on SSL applicato tramite i componenti aggiuntivi di Heroku prima se si utilizza il proprio certificato, sottodomini ecc.

Quindi basta aggiungere quanto segue per eseguire il reindirizzamento da qualsiasi elemento diverso da HTTPS a HTTPS. Questo è molto vicino alla risposta accettata sopra, ma:

  1. Ti assicura di utilizzare “app.use” (per tutte le azioni, non solo per ottenere)
  2. Esplicita esplicitamente la logica forceSsl in una funzione dichiarata
  3. Non usa ‘*’ con “app.use” – questo in realtà non è riuscito quando l’ho provato.
  4. Qui, voglio solo SSL in produzione. (Cambia come si adatta alle tue esigenze)

Codice:

  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 per gli utenti SailsJS (0.10.x). Puoi semplicemente creare una policy (enforceSsl.js) all’interno di 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(); } }; 

Quindi riferimento da config / policies.js insieme a qualsiasi altro criterio, ad esempio:

‘*’: [‘authenticated’, ‘enforceSsl’]

La risposta è usare l’intestazione di ‘x-forwarded-proto’ che Heroku inoltra mentre fa il proxy thingamabob. (nota a margine: passano anche molte altre variabili x che possono essere utili, controllarle ).

Il mio codice:

 /* 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 */ }) 

Grazie Brandon, stavo solo aspettando quella cosa di ritardo di 6 ore che non mi avrebbe permesso di rispondere alla mia stessa domanda.

La risposta accettata ha un dominio hardcoded in esso, che non è troppo buono se si ha lo stesso codice su diversi domini (ad esempio: dev-yourapp.com, test-yourapp.com, yourapp.com).

Usa questo invece:

 /* 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/

Ho scritto un piccolo modulo di nodo che applica SSL ai progetti espressi. Funziona sia in situazioni standard che in caso di proxy inversi (Heroku, nodejitsu, ecc.)

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

Se vuoi testare l’intestazione x-forwarded-proto sul tuo localhost, puoi usare nginx per configurare un file vhost che trasmette tutte le richieste all’app del tuo nodo. Il tuo file di configurazione vgin nginx potrebbe assomigliare a questo

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; } } 

I bit importanti qui sono che stai trasmettendo tutte le richieste alla porta localhost 3000 (qui è dove è in esecuzione l’app del tuo nodo) e stai configurando una serie di intestazioni tra cui X-Forwarded-Proto

Quindi nella tua app rilevi quella intestazione come al solito

Esprimere

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

host

Infine devi aggiungere questa linea al tuo file hosts

 127.0.0.1 dummy.com 

Se stai utilizzando cloudflare.com come CDN in combinazione con heroku, puoi abilitare il reindirizzamento automatico ssl all’interno di cloudflare in questo modo:

  1. Accedi e vai alla tua dashboard

  2. Seleziona le regole della pagina

    Seleziona le regole della pagina

  3. Aggiungi il tuo dominio, ad esempio http://www.example.com e triggers sempre https su on Switch usa sempre https su on

Gli utenti di loopback possono utilizzare una versione leggermente adattata della risposta di arcseldon come middleware:

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

Dovresti dare un’occhiata a heroku-ssl-redirect . Esso funziona magicamente!

 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); 

Il controllo del protocollo nell’intestazione X-Forwarded-Proto funziona bene su Heroku, proprio come ha fatto notare Derek. Per quello che vale, ecco una sintesi del middleware Express che utilizzo e il test corrispondente.

 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 */ } }); 

Un modo più esplicito per farlo.

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