it-swarm.com.de

Heroku NodeJS http zu https SSL erzwungene Weiterleitung

Ich habe eine Anwendung, die auf heroku mit express on node mit https ausgeführt wird. Wie identifiziere ich das Protokoll, um eine Weiterleitung zu https mit nodejs auf Heroku zu erzwingen?

Meine App ist nur ein einfacher http-Server. Sie erkennt (noch) nicht, dass Heroku https-Anfragen sendet:

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

Die Antwort ist, den Header von 'x-forwarded-proto' zu verwenden, den Heroku weitergibt, wie es sein Proxy-Dingamabob tut. (Nebenbemerkung: Sie übergeben auch einige andere x-Variablen, die nützlich sein könnten, check out ).

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

Danke Brandon, ich habe nur auf diesen 6-Stunden-Verspätungswunsch gewartet, der mich meine eigene Frage nicht beantworten lassen würde.

92

Seit heute 10. Oktober 2014 unter Verwendung von Heroku Cedar stack und ExpressJS ~ 3.4.4 ist hier eine funktionierende Menge von Code. 

Das Wichtigste dabei ist, dass wir uns bei Heroku befinden. Die SSL-Beendigung erfolgt beim Load Balancer, bevor der verschlüsselte Datenverkehr Ihre Knoten-App erreicht. Mit req.headers ['x-forwarded-proto'] === 'https' kann geprüft werden, ob https für die Anforderung verwendet wurde.

Wir müssen uns nicht darum kümmern, lokale SSL-Zertifikate in der App usw. zu haben, wie dies beim Hosting in anderen Umgebungen der Fall ist. Sie sollten jedoch zuerst ein SSL-Add-On über Heroku-Add-Ons erhalten, wenn Sie Ihr eigenes Zertifikat, Subdomains usw. verwenden.

Fügen Sie einfach Folgendes hinzu, um die Umleitung von etwas anderem als HTTPS zu HTTPS durchzuführen. Dies kommt der oben akzeptierten Antwort sehr nahe, aber: 

  1. Stellt sicher, dass Sie "app.use" verwenden (für alle Aktionen, nicht nur abrufen)
  2. Externalisiert die forceSsl-Logik explizit in eine deklarierte Funktion
  3. Verwendet '*' nicht mit "app.use" - dies schlug tatsächlich fehl, wenn ich testete es. 
  4. Hier möchte ich nur SSL in der Produktion. (Ändern Sie nach Ihren Bedürfnissen)

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

Hinweis für Benutzer von SailsJS (0.10.x). Sie können einfach eine Richtlinie (enforceSsl.js) innerhalb von API/Policies erstellen:

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

Verweisen Sie dann zusammen mit allen anderen Richtlinien auf config/policy.js, z.

'*': ['authentifiziert', 'enforceSsl']

98
arcseldon

Die akzeptierte Antwort enthält eine fest codierte Domäne, die nicht zu gut ist, wenn Sie denselben Code auf mehreren Domänen verwenden (z. B. dev-yourapp.com, test-yourapp.com, yourapp.com).

Verwenden Sie stattdessen diese:

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

20

Ich habe ein kleines Knotenmodul geschrieben, das SSL für Expressprojekte erzwingt. Es funktioniert sowohl in Standardsituationen als auch bei umgekehrten Proxies (Heroku, Nodejitsu usw.).

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

16
florian

Wenn Sie den x-forwarded-proto-Header auf Ihrem localhost testen möchten, können Sie mit nginx eine vhost-Datei einrichten, die alle Anforderungen an Ihre Knoten-App übermittelt. Ihre nginx vhost-Konfigurationsdatei könnte so aussehen

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

Die wichtigsten Punkte hier sind, dass Sie alle Anforderungen an den localhost-Port 3000 weiterleiten (dort, wo Ihre Knoten-App ausgeführt wird) und Sie eine Reihe von Headern einrichten, einschließlich X-Forwarded-Proto.

Dann erkennen Sie in Ihrer App diesen Header wie gewohnt

Ausdrücken

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

Gastgeber

Zum Schluss müssen Sie diese Zeile zu Ihrer hosts-Datei hinzufügen

127.0.0.1 dummy.com
6
simo

Wenn Sie cloudflare.com als CDN in Kombination mit heroku verwenden, können Sie die automatische SSL-Weiterleitung in cloudflare einfach wie folgt aktivieren:

  1. Melden Sie sich an und gehen Sie zu Ihrem Dashboard

  2. Wählen Sie Seitenregeln aus

    Select Page Rules

  3. Fügen Sie Ihre Domain hinzu, z. www.example.com und schalten Sie immer https ein Switch always use https to on
4
Ben Marten

Loopback-Benutzer können eine leicht angepasste Version von arcseldon answer als Middleware verwenden:

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

Sie sollten einen Blick auf heroku-ssl-redirect werfen. Es wirkt wie ein Zauber!

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

Die Überprüfung des Protokolls im X-Forwarded-Proto-Header funktioniert auf Heroku einwandfrei, genau wie Derek es angedeutet hat. Für was es wert ist, hier ist ein Gist der Express Middleware, die ich verwende, und des entsprechenden Tests.

0
Peter Marklund

Eine spezifischere Möglichkeit, dies zu tun.

  app.enable('trust proxy');
  app.use('*', (req, res, next) => {
    if (req.secure) {
      return next();
    }
    res.redirect(`https://${req.hostname}${req.url}`);
  });
0
denixtry
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 */
  }
});
0
Chiedo