J'ai une application en marche sur heroku avec express sur noeud avec https ,. Comment identifier le protocole pour forcer une redirection vers https avec nodejs sur heroku?
Mon application n'est qu'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);
La solution consiste à utiliser l'en-tête de 'x-forwarded-proto' que Heroku transmet de la même manière que son mandataire proxy. (note latérale: Ils transmettent aussi plusieurs autres variables x qui pourraient ê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, attendais ce délai de 6 heures qui ne me permettait pas de répondre à ma propre question.
À compter d'aujourd'hui, le {10 octobre 2014}, en utilisant pile de cèdres Heroku et ExpressJS ~ 3.4.4, voici un ensemble de code fonctionnel.
La principale chose à retenir ici est que nous déployons à Heroku. La terminaison SSL a lieu au niveau de l'équilibreur de charge, avant que le trafic crypté n'atteigne votre application de nœud. Il est possible de tester si https a été utilisé pour effectuer la demande avec req.headers ['x-forwarded-proto'] === 'https'.
Nous n'avons pas besoin de nous inquiéter d'avoir des certificats SSL locaux dans l'application, comme vous pourriez le faire si vous hébergez dans d'autres environnements. Cependant, vous devriez d'abord appliquer un add-on SSL via les add-ons Heroku si vous utilisez votre propre certificat, vos sous-domaines, etc.
Ensuite, ajoutez ce qui suit pour faire la redirection à partir de n’importe quoi autre que HTTPS vers HTTPS. Ceci est très proche de la réponse acceptée ci-dessus, mais:
- Vous assure d'utiliser "app.use" (pour toutes les actions, pas seulement pour obtenir)
- Externalise explicitement la logique forceSsl dans une fonction déclarée
- N'utilise pas '*' avec "app.use" - cela a échoué lorsque I testé
- 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 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();
}
};
Ensuite, faites référence à config/policies.js avec toute autre politique, par exemple:
'*': ['authentifié', 'enforceSsl']
La réponse acceptée contient un domaine codé en dur, ce qui n'est pas si bon si vous avez le même code dans plusieurs domaines (par exemple: 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 module de petit nœud qui applique SSL sur les projets express. Cela fonctionne aussi bien dans les situations standard que dans les proxies inversés (Heroku, nodejitsu, etc.)
Si vous souhaitez tester l'en-tête x-forwarded-proto
sur votre hôte local, vous pouvez utiliser nginx pour configurer un fichier vhost qui envoie toutes les demandes à votre application de noeud. Votre fichier de configuration nginx vhost pourrait ressembler à ceci
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;
}
}
Les éléments importants ici sont que vous soumettez toutes les demandes au serveur localhost 3000 (c'est ici que votre application de noeud s'exécute) et que vous configurez plusieurs en-têtes, dont X-Forwarded-Proto
.
Puis, dans votre application, détectez cet en-tête comme d'habitude
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
})
Enfin, vous devez ajouter 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 SSL automatiquement dans cloudflare comme suit:
Connectez-vous et accédez à votre tableau de bord
Sélectionner les règles de la page
Les utilisateurs en boucle peuvent utiliser une version légèrement adaptée de arcseldon answer comme 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/serveur.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 bien sur Heroku, comme l'a souligné Derek. Pour ce que ça vaut, voici un Gist du middleware Express que j’utilise et de son test correspondant.
Une façon 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}`);
});
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 */
}
});