Heroku NodeJS http à https ssl a forcé la redirection

J’ai une application qui fonctionne sur heroku avec express sur le nœud avec https ,. Comment identifier le protocole pour forcer une redirection vers https avec nodejs sur heroku?

Mon application est juste un simple serveur http, elle ne réalise pas (encore) que heroku lui envoie des requêtes https:

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

À compter d’aujourd’hui, le 10 octobre 2014 , en utilisant la stack de cèdres Heroku et ExpressJS ~ 3.4.4 , voici un ensemble de code fonctionnel.

La principale chose à retenir ici est que nous sums en train de nous déployer à Heroku. La terminaison SSL se produit au niveau de l’équilibreur de charge, avant que le trafic chiffré n’atteigne votre application de noeud. Il est possible de tester si https a été utilisé pour créer la requête avec req.headers [‘x-forwarded-proto’] === ‘https’ .

Nous n’avons pas besoin de nous préoccuper d’avoir des certificates SSL locaux dans l’application, comme vous le feriez si vous hébergiez dans d’autres environnements. Cependant, vous devriez d’abord obtenir un complément SSL via les modules complémentaires Heroku si vous utilisez votre propre certificate, sous-domaine, etc.

Ajoutez simplement les éléments suivants pour effectuer la redirection à partir de toute autre chose que HTTPS vers HTTPS. Ceci est très proche de la réponse acceptée ci-dessus, mais:

  1. S’assure que vous utilisez “app.use” (pour toutes les actions, pas seulement pour obtenir)
  2. Externe explicitement la logique forceSsl dans une fonction déclarée
  3. N’utilise pas “*” avec “app.use” – cela a échoué lorsque je l’ai testé.
  4. Ici, je ne veux que SSL en production. (Changer selon vos besoins)

Code:

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

Remarque pour les utilisateurs de SailsJS (0.10.x). Vous pouvez simplement créer une politique (enforceSsl.js) dans api / policies:

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

Puis référence de config / policies.js avec d’autres politiques, par exemple:

‘*’: [‘authentifié’, ‘enforceSsl’]

La réponse est d’utiliser l’en-tête de ‘x-forwarded-proto’ que Heroku transmet comme il est proxy thingamabob. (remarque: ils transmettent également plusieurs autres variables x qui peuvent être utiles, vérifiez-les ).

Mon code:

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

Merci Brandon, attendait juste ce retard de 6 heures qui ne me permettrait pas de répondre à ma propre question.

La réponse acceptée contient un domaine codé en dur, ce qui n’est pas très bien si vous avez le même code sur plusieurs domaines (ex: dev-yourapp.com, test-yourapp.com, yourapp.com).

Utilisez ceci à la place:

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

J’ai écrit un petit module de nœud qui applique SSL sur les projets express. Cela fonctionne à la fois dans les situations standard et en cas de proxies inverses (Heroku, nodejitsu, etc.)

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

Si vous souhaitez tester l’en x-forwarded-proto tête x-forwarded-proto sur votre hôte local, vous pouvez utiliser nginx pour configurer un fichier vhost qui transmet toutes les requêtes à votre application de noeud. Votre fichier de configuration nginx vhost pourrait ressembler à ceci

NginX

 server { listen 80; listen 443; server_name dummy.com; ssl on; ssl_certificatee /absolute/path/to/public.pem; ssl_certificatee_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; } } 

Les points importants ici sont que vous dépassez toutes les requêtes sur le port 3000 de localhost (c’est là que fonctionne l’application de votre noeud) et vous configurez un tas d’en-têtes, y compris X-Forwarded-Proto

Ensuite, dans votre application, détectez cet en-tête comme d’habitude

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

Hôtes

Enfin, vous devez append cette ligne à votre fichier hosts

 127.0.0.1 dummy.com 

Si vous utilisez cloudflare.com en tant que CDN en combinaison avec heroku, vous pouvez activer la redirection automatique de SSL dans cloudflare comme ceci:

  1. Connectez-vous et accédez à votre tableau de bord

  2. Sélectionner les règles de la page

    Sélectionner les règles de la page

  3. Ajoutez votre domaine, par exemple http://www.example.com, et utilisez toujours https pour activer Le commutateur utilise toujours https pour activer

Les utilisateurs de Loopback peuvent utiliser une version légèrement adaptée d’Arcseldon en tant que middleware:

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

serveur / server.js

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

Vous devriez jeter un oeil à heroku-ssl-redirect . Il fonctionne comme un charme!

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

Vérifier le protocole dans l’en-tête X-Forwarded-Proto fonctionne très bien sur Heroku, comme l’a souligné Derek. Pour ce que cela vaut, voici un aperçu du middleware Express que j’utilise et de son test correspondant.

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

Une manière spécifique plus expressive de le faire.

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