Heroku NodeJS http para https ssl redirecionamento forçado

Eu tenho um aplicativo instalado e funcionando no heroku com expressa no nó com https ,. Como faço para identificar o protocolo para forçar um redirecionamento para https com nodejs no heroku?

Meu aplicativo é apenas um servidor http simples, ele (ainda) não percebe que o heroku está enviando solicitações https:

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

A partir de hoje, 10 de outubro de 2014 , usando o Heroku Cedar stack e o ExpressJS ~ 3.4.4 , aqui está um conjunto de código de trabalho.

A principal coisa a lembrar aqui é que estamos implantando para Heroku. A terminação SSL ocorre no balanceador de carga, antes que o tráfego criptografado chegue ao aplicativo do nó. É possível testar se o https foi usado para fazer o pedido com req.headers [‘x-forwarded-proto’] === ‘https’ .

Nós não precisamos nos preocupar em ter certificados SSL locais dentro do aplicativo, etc, como você poderia se hospedar em outros ambientes. No entanto, você deve obter um Complemento SSL aplicado via Complementos Heroku primeiro se usar seu próprio certificado, subdomínios etc.

Em seguida, basta adicionar o seguinte para fazer o redirecionamento de qualquer coisa diferente de HTTPS para HTTPS. Isso está muito próximo da resposta aceita acima, mas:

  1. Garante que você use “app.use” (para todas as ações, não apenas para obter)
  2. Explicitamente externaliza a lógica forceSsl em uma function declarada
  3. Não usa ‘*’ com “app.use” – isso realmente falhou quando eu testei.
  4. Aqui, só quero SSL em produção. (Mude conforme suas necessidades)

Código:

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

Nota para usuários do SailsJS (0.10.x). Você pode simplesmente criar uma política (enforceSsl.js) dentro de 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(); } }; 

Então, faça referência a config / policies.js junto com outras políticas, por exemplo:

‘*’: [‘autenticado’, ‘enforceSsl’]

A resposta é usar o header do ‘x-forwarded-proto’ que o Heroku transmite como faz o proxy thingamabob. (nota lateral: Eles também passam várias outras variables-x que podem ser úteis, verifique-as ).

Meu código:

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

Obrigado Brandon, estava apenas esperando por aquela coisa de atraso de 6 horas que não me deixaria responder a minha própria pergunta.

A resposta aceita tem um domínio codificado, o que não é muito bom se você tiver o mesmo código em vários domínios (por exemplo: dev-yourapp.com, test-yourapp.com, yourapp.com).

Use isso em vez disso:

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

Eu escrevi um pequeno módulo de nó que impõe o SSL em projetos expressos. Funciona tanto em situações padrão quanto no caso de proxies reversos (Heroku, nodejitsu, etc.)

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

Se você quiser testar o header x-forwarded-proto no seu host local, você pode usar o nginx para configurar um arquivo vhost que faz o proxy de todas as solicitações para o aplicativo do nó. Seu arquivo de configuração nginx vhost pode ser assim

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

Os bits importantes aqui são que você está intermediando todos os pedidos para a porta localhost 3000 (é onde seu aplicativo de nó está rodando) e você está configurando um monte de headers incluindo o X-Forwarded-Proto

Em seguida, no seu aplicativo, detecte esse header como de costume

Expressar

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

Hosts

Finalmente você tem que adicionar esta linha ao seu arquivo hosts

 127.0.0.1 dummy.com 

Se você estiver usando cloudflare.com como CDN em combinação com o heroku, poderá ativar o redirecionamento ssl automático dentro do cloudflare facilmente assim:

  1. Faça o login e vá para o seu painel

  2. Selecione as regras da página

    Selecione as regras da página

  3. Adicione seu domínio, por exemplo, http://www.example.com e mude sempre para usar https em Mudar sempre use https para on

Os usuários de loopback podem usar uma versão ligeiramente adaptada da resposta do arcseldon como middleware:

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

Você deve dar uma olhada no heroku-ssl-redirect . Ele funciona como um encanto!

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

Verificar o protocolo no header X-Forwarded-Proto funciona bem no Heroku, assim como o Derek apontou. Por que vale a pena, aqui está uma essência do middleware Express que eu uso e seu teste correspondente.

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

Uma maneira específica mais expressa para fazer isso.

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