Estoy tratando de crear un middleware para Express.js para redirigir todos los no-segura (puerto 80) tráfico para el seguro SSL (puerto 443).
Desafortunadamente, no hay información en un Express.js solicitar que permite determinar si la petición viene a través de http o https.

Una solución sería redirigir cada solicitud, pero esta no es una opción para mí.

Notas:

  1. No hay ninguna posibilidad de manejarlo con Apache o algo más. Es ha a realizarse en el nodo.

  2. Sólo uno servidor puede ser despedido en la aplicación.

¿Cómo se podría solucionar eso?

  • Es posible duplicar stackoverflow.com/questions/7450940/…
  • La solución a este problema es redirigir todas las peticiones. Pero como escribí, eso no es una opción.
  • Sólo redirige las peticiones que vienen a través de http.
  • Eso es correcto, había que añadir una segunda nota. Sólo un servidor permitido.
  • No creo que usted podría estar hablando de 2 protocolos en el mismo socket. Yo podría estar equivocado.
  • es inusual, pero usted puede: serverfault.com/a/342378/47187
  • Hay una posibilidad para averiguar si hay una conexión TLS establecido. expressjs.com/en/api.html#req.secure . No sé cuando se añadió a pesar de que.

InformationsquelleAutor Elias | 2011-12-22

8 Comentarios

  1. 50

    Sólo en caso de que usted es anfitrión en Heroku y sólo quiere dirigir a HTTPS independientemente del puerto, aquí está la solución de middleware que estamos usando.

    No se molesta para redirigir si usted está desarrollando a nivel local.

    function requireHTTPS(req, res, next) {
      //The 'x-forwarded-proto' check is for Heroku
      if (!req.secure && req.get('x-forwarded-proto') !== 'https' && process.env.NODE_ENV !== "development") {
        return res.redirect('https://' + req.get('host') + req.url);
      }
      next();
    }

    Se puede utilizar con Express (2.x y 4.x) como:

    app.use(requireHTTPS);
    • Solución agradable. El único problema que veo con esto es que es el reenvío de todos los métodos http, no se tal vez volver 403 en todo lo que no consigue.
    • Para los principiantes entre nosotros: Recuerda poner el app.use(requireHTTPS) llamada antes de cualquier app.get llamadas (antes de que cualquier cosa que debe ser protegida por SSL).
  2. 26

    Aunque la pregunta parece de un año de edad, me gustaría contestar, ya que podría ayudar a los demás. Su realmente sencillo con la última versión de expressjs (2.x). Primero crear la clave y el cert utilizando este código

    openssl genrsa -out ssl-key.pem 1024

    $ openssl req -new -key ssl-key.pem -out certrequest.csr
    .. montón de peticiones

    $ openssl x509 -req -in certrequest.csr -signkey ssl-key.pem -out ssl-cert.pem

    Almacenar el certificado y la clave de los archivos en la carpeta que contiene app.js. A continuación, edite el app.js archivo y escribir el siguiente código antes de expresar.createServer()

    var https = require('https');
    var fs = require('fs');
    
    var sslkey = fs.readFileSync('ssl-key.pem');
    var sslcert = fs.readFileSync('ssl-cert.pem')
    
    var options = {
        key: sslkey,
        cert: sslcert
    };

    Ahora pasar el options objeto en el createServer() función

    express.createServer(options);

    Hecho!

  3. 21

    Primero, déjame ver si puedo aclarar el problema. Usted está limitado a un (1) node.js proceso, pero ese proceso puede escuchar en dos (2) puertos de red, tanto de 80 y 443, ¿verdad? (Cuando digo uno servidor no está claro si se refiere a un proceso o sólo un puerto de red).

    Dado que la restricción, usted problema parece ser, por razones que no proporcionan, de alguna manera, sus clientes se conectan al puerto equivocado. Este es un extraño caso extremo porque, de forma predeterminada, los clientes podrán hacer peticiones HTTP al puerto 80 y HTTPS en el puerto 443. Y cuando digo «por defecto», me refiero a que si no hay puertos específicos se incluyen en la Url. Así que a menos que usted está utilizando explícitamente atravesado URLs como http://example.com:443 y https://example.com:80, usted realmente no debería tener ningún atravesado el tráfico de golpear a su sitio. Pero ya que la pregunta, supongo que debe tener, aunque apuesto a que usted está usando los puertos no estándar como contraposición a la 80/443 valores predeterminados.

    Así, para el fondo: SÍ, algunos servidores web de manejar esta razonablemente bien. Por ejemplo, si usted http://example.com:443 a nginx, responderá con un HTTP 400 «Solicitud incorrecta» la respuesta que indica «La llanura de la solicitud HTTP fue enviado a puerto HTTPS». SÍ, usted puede escuchar en tanto el 80 y 443 de la misma node.js proceso. Usted sólo tiene que crear 2 instancias independientes de express.createServer(), así que no hay problema. Aquí es un simple programa para demostrar el manejo de ambos protocolos.

    var fs = require("fs");
    var express = require("express");
    
    var http = express.createServer();
    
    var httpsOptions = {
      key: fs.readFileSync('key.pem'),
      cert: fs.readFileSync('cert.pem')
    };
    
    var https = express.createServer(httpsOptions);
    
    http.all('*', function(req, res) {
      console.log("HTTP: " + req.url);
      return res.redirect("https://" + req.headers["host"] + req.url);
    });
    
    http.error(function(error, req, res, next) {
      return console.log("HTTP error " + error + ", " + req.url);
    });
    
    https.error(function(error, req, res, next) {
      return console.log("HTTPS error " + error + ", " + req.url);
    });
    
    https.all('*', function(req, res) {
      console.log("HTTPS: " + req.url);
      return res.send("Hello, World!");
    });
    
    http.listen(80);

    Y puedo probar este a través de curvatura como este:

    $ curl --include --silent http://localhost/foo
    HTTP/1.1 302 Moved Temporarily
    X-Powered-By: Express
    Content-Type: text/html
    Location: https://localhost/foo
    Connection: keep-alive
    Transfer-Encoding: chunked
    
    <p>Moved Temporarily. Redirecting to <a href="https://localhost/foo">https://localhost/foo</a></p>
    
    $ curl --include --silent --insecure https://localhost:443/foo
    HTTP/1.1 200 OK
    X-Powered-By: Express
    Content-Type: text/html; charset=utf-8
    Content-Length: 13
    Connection: keep-alive
    
    Hello, World!%

    Y mostrando la redirección de HTTP a HTTPS…

    curl --include --silent --location --insecure 'http://localhost/foo?bar=bux'
    HTTP/1.1 302 Moved Temporarily
    X-Powered-By: Express
    Content-Type: text/html
    Location: https://localhost/foo?bar=bux
    Connection: keep-alive
    Transfer-Encoding: chunked
    
    HTTP/1.1 200 OK
    X-Powered-By: Express
    Content-Type: text/html; charset=utf-8
    Content-Length: 13
    Connection: keep-alive
    
    Hello, World!%

    Por lo que trabajará para servir tanto a los protocolos para el caso regulares y redirigir correctamente. Sin embargo, criss-cruces no funcionan en absoluto. Yo creo que una atravesado solicitud de golpear a un server express no va a ser encaminados a través de la pila de middleware porque va a ser tratado como un error desde el principio y ni siquiera se llega a la URI de la solicitud se analiza correctamente, que es necesario enviar a través de la ruta del middleware de la cadena. El expreso de la pila, ni siquiera se les creo porque ellos no son válidas las solicitudes, por lo que son ignorados en algún lugar en el nodo de la pila TCP. Probablemente es posible escribir un servidor para ello, y no puede ya ser un módulo por ahí, pero usted tendría que escribir en la capa TCP directamente. Y usted tendría que detectar regular de la petición HTTP en el primer fragmento de los datos de cliente que llega al puerto TCP y el alambre de conexión a un servidor HTTP en lugar de la normal, TLS handshake.

    Cuando hago alguna de estas, mi expreso de los controladores de error NO se llama.

    curl  --insecure https://localhost:80/foo
    curl: (35) Unknown SSL protocol error in connection to localhost:80
    
    curl http://localhost:443/foo
    curl: (52) Empty reply from server
    • Pregunta de seguridad: supongamos que una aplicación utiliza la cookie de autenticación y alguien que se registra en navega a una » http://… parte del sitio, es posible que un atacante podría oler su cookie antes de la redirección que sucede?
    • Sí, yo creo que es posible, que es la razón por la que debe establecer el «Seguro» de la bandera en su cookie de cabecera, que le indican a los navegadores no transmitir la cookie a través de HTTP, sólo HTTPS. en.wikipedia.org/wiki/HTTP_cookie#Secure_and_HttpOnly
    • Bien, muy bien! Sólo tengo que averiguar cómo llegar a CouchDB para establecer un Seguro de Bandera. Gracias!!
    • Si express le dice que no lo llame createServerstackoverflow.com/questions/11804202/…
    • Por favor, puedes hacer esto con JavaScript por Pila de directrices?
  4. 10

    Basado en Elias respuesta pero con código en línea. Esto funciona si tienes nodo detrás de nginx o un equilibrador de carga. Nginx o el equilibrador de carga siempre hit nodo con el viejo y simple de http, pero establece un encabezado de modo que pueda distinguir.

    app.use(function(req, res, next) {
      var schema = req.headers['x-forwarded-proto'];
    
      if (schema === 'https') {
        //Already https; don't do anything special.
        next();
      }
      else {
        //Redirect to https.
        res.redirect('https://' + req.headers.host + req.url);
      }
    });
    • Hacer esto es vulnerable a un hombre en medio de los ataques. Ver HSTS: en.wikipedia.org/wiki/HTTP_Strict_Transport_Security
    • La respuesta de @jonathon-tran es correcto y no es más vulnerable que el hombre en el centro de los ataques de no hacerlo. HSTS es una protección adicional en contra de ellos para que los clientes que te gustaría idealmente desea utilizar en conjunción con algo como esto (aunque todavía no es compatible con IE como de IE 11).
    • Me sale este error de chrome: ERR_TOO_MANY_REDIRECTS
    • He encontrado esta respuesta y funcionó: stackoverflow.com/questions/10697660/force-ssl-with-expressjs-3
  5. 3

    http.createServer(app.el asa).escuchar(80)

    https.createServer(opciones de la aplicación.el asa).escuchar(443)

    para expresar 2x

  6. 2

    Probar este ejemplo :

    var express = require('express');
            var app = express();
            //set up a route to redirect http to https
            app.use(function (req, res, next) {
            if (!/https/.test(req.protocol)) {
                res.redirect("https://" + req.headers.host + req.url);
            } else {
                return next();
            }
            });
            var webServer = app.listen(port, function () {
                console.log('Listening on port %d', webServer.address().port);
            });
  7. -1

    Desde que estaba trabajando en nginx, tuve acceso a la cabecera x-forwarded-proto propiedad para que yo pudiera escribir una pequeña middleware para redirigir todo el tráfico como se describe aquí: http://elias.kg/post/14971446990/force-ssl-with-express-js-on-heroku-nginx

    Edit: Actualizado la url

    • Esta página se ha ido, así que estoy downvoting. Si se vuelve a subir por favor hágamelo saber para que yo pueda votar de nuevo! Esto podría haber sido evitado mediante la reproducción de algunos de los contenidos aquí. Gracias.
    • Gracias por la info, he actualizado la url
    • Excelente! Cambiado mi voto. (En retrospectiva, probablemente debería haber dejado un comentario, y no votada abajo de ella.)
    • Su página es hacia abajo de nuevo…
    • Copia en caché de la aquí. Alternativamente, consulte Jonathan Tran respuesta que es prácticamente una copia del código de la entrada.
    • Votada abajo porque el enlace está inactivo.
    • El enlace no funciona

Dejar respuesta

Please enter your comment!
Please enter your name here