node.js - https node js express
Cómo forzar SSL/https en Express.js (8)
Aunque la pregunta parece tener un año, me gustaría responder, ya que podría ayudar a otros. Es realmente muy simple con la última versión de expressjs (2.x). Primero crea la clave y cert usando este código
openssl genrsa -out ssl-key.pem 1024
$ openssl req -new -key ssl-key.pem -out certrequest.csr
.. $ openssl req -new -key ssl-key.pem -out certrequest.csr
instrucciones
$ openssl x509 -req -in certrequest.csr -signkey ssl-key.pem -out ssl-cert.pem
Almacene los archivos cert y key en la carpeta que contiene app.js. A continuación, edite el archivo app.js y escriba el siguiente código antes de express.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 pase el objeto de options
en la función createServer ()
express.createServer(options);
¡Hecho!
Estoy intentando crear un middleware para Express.js para redirigir todo el tráfico no seguro (puerto 80) al puerto SSL seguro (443). Lamentablemente, no hay información en una solicitud de Express.js que le permita determinar si la solicitud proviene de http o https.
Una solución sería redirigir todas las solicitudes, pero esta no es una opción para mí.
Notas:
No hay posibilidad de manejarlo con Apache o algo más. Tiene que hacerse en nodo.
Solo se puede activar un servidor en la aplicación.
¿Cómo resolverías eso?
Basado en la respuesta de Elias pero con código en línea. Esto funciona si tiene un nodo detrás de nginx o un equilibrador de carga. Nginx o el equilibrador de carga siempre golpearán el nodo con el viejo HTTP plano, pero establece un encabezado para 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);
}
});
Desde que estaba trabajando en nginx, tuve acceso a la propiedad x-forward-proto del encabezado para poder escribir un pequeño middleware para redirigir todo el tráfico como se describe aquí: http://elias.kg/post/14971446990/force-ssl-with-express-js-on-heroku-nginx
Editar: Actualizó la url
En caso de que esté alojando en Heroku y solo quiera redireccionar a HTTPS independientemente del puerto, aquí está la solución de middleware que estamos usando.
No se molesta en redireccionar si se está desarrollando localmente.
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();
}
Puede usarlo con Express (2.x y 4.x) así:
app.use(requireHTTPS);
Este código parece que hace lo que necesita: https://gist.github.com/903596
Primero, déjame ver si puedo aclarar el problema. Está limitado a un (1) proceso node.js, pero ese proceso puede escuchar en dos (2) puertos de red, tanto 80 como 443, ¿no? (Cuando dices un servidor no está claro si te refieres a un proceso o solo a un puerto de red).
Dada esa restricción, su problema parece ser que, por razones que no proporciona, de alguna manera sus clientes se están conectando al puerto equivocado. Este es un caso extremo extraño porque, de forma predeterminada, los clientes realizarán solicitudes HTTP al puerto 80 y HTTPS al puerto 443. Y cuando digo "por defecto", quiero decir si no se incluyen puertos específicos en las URL. Por lo tanto, a menos que esté usando explícitamente URL entrecruzadas como http://example.com:443 y https://example.com:80 , realmente no debería tener ningún tráfico entrelazado que llegue a su sitio. Pero desde que hizo la pregunta, creo que debe tenerla, aunque apuesto a que está utilizando puertos no estándar en comparación con los valores predeterminados de 80/443.
Entonces, para el fondo: SÍ algunos servidores web manejan esto razonablemente bien. Por ejemplo, si hace http://example.com:443 a nginx, responderá con una respuesta HTTP 400 "Solicitud incorrecta" que indica "La solicitud HTTP simple se envió al puerto HTTPS". SÍ, puede escuchar tanto en 80 como en 443 desde el mismo proceso node.js. Solo necesita crear 2 instancias separadas de express.createServer()
, así que no hay problema. Aquí hay un programa simple 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 esto a través de cURL así:
$ 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!%
Entonces eso funcionará para servir a ambos protocolos para el caso regular y redirigir adecuadamente. Sin embargo, los cruces cruzados no funcionan en absoluto. Creo que una solicitud entrecruzada que llegue a un servidor Express no se enrutará a través de la pila de middleware, ya que se tratará como un error desde el principio y ni siquiera se analizará correctamente el URI de solicitud, lo cual es necesario para enviarlo a través de la cadena middleware de ruta. La pila express ni siquiera los obtiene, creo que porque no son solicitudes válidas, por lo que se ignoran en algún lugar de la pila TCP del nodo. Probablemente sea posible escribir un servidor para hacer esto, y puede que ya exista un módulo, pero tendría que escribirlo en la capa TCP directamente. Y tendría que detectar una solicitud HTTP regular en el primer fragmento de datos del cliente que golpea el puerto TCP y conectar esa conexión a un servidor HTTP en lugar de su protocolo de enlace TLS normal.
Cuando hago cualquiera de estos, mis controladores de errores expresos NO reciben llamadas.
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
http.createServer (app.handle) .listen (80)
https.createServer (opciones, app.handle) .listen (443)
para expreso 2x
Prueba 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);
});