Heroku NodeJS http到https ssl强制重定向

Der*_*ner 100 ssl https redirect heroku node.js

我有一个应用程序启动并运行在heroku上使用https表达节点.如何识别强制重定向到heroku上的nodejs的协议?

我的应用程序只是一个简单的http服务器,它(尚未)实现heroku发送它的https请求:

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

arc*_*don 105

截至2014年10月10日,使用Heroku Cedar堆栈ExpressJS~3.4.4,这是一组有效的代码.

这里要记住的主要事情是我们正在部署到Heroku.在加密流量到达您的节点应用之前,SSL终止发生在负载均衡器上.可以使用req.headers ['x-forwarded-proto'] ==='https'来测试https是否用于发出请求.

我们不需要关心在应用程序内部使用本地SSL证书,就像在其他环境中托管一样.但是,如果使用您自己的证书,子域等,您应首先通过Heroku加载项获得SSL加载项.

然后,只需添加以下内容即可从HTTPS以外的任何位置重定向到HTTPS.这非常接近上面接受的答案,但是:

  1. 确保您使用"app.use"(适用于所有操作,而不仅仅是获取)
  2. 将forceSsl逻辑显式地外部化为声明的函数
  3. 不使用'*'和"app.use" - 这在我测试时实际上失败了.
  4. 在这里,我只想在生产中使用SSL.(根据您的需要改变)

码:

 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...
}
Run Code Online (Sandbox Code Playgroud)

SailsJS(0.10.x)用户注意事项.您只需在api/policies中创建一个策略(enforceSsl.js):

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();
  }
};
Run Code Online (Sandbox Code Playgroud)

然后从config/policies.js引用以及任何其他策略,例如:

'*':['authenticated','enforceSsl']

  • 另外,请注意`res.redirect`这默认为302重定向(至少在express 4.x中).对于SEO和缓存的原因,您可能需要301重定向.替换`返回res.redirect相应的行(301,[ '的https://',req.get( '主机'),req.url].加入( ''));` (8认同)
  • 注意:在`Express 4.x`中,删除`app.configure`行,然后使用内部药水.`app.configure`是遗留代码,不再包含在express中. (4认同)
  • "下表列出了Express 4的其它小但重要的变化:....()函数已被删除app.configure使用process.env.NODE_ENV或app.get('ENV’)功能,探测环境和相应地配置应用程序." (2认同)

Der*_*ner 93

答案是使用Heroku传递的'x-forwarded-proto'的标题,因为它是代理的thingamabob.(旁注:他们也传递了其他几个可能很方便的x变量,检查出来).

我的代码:

/* 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 */
})
Run Code Online (Sandbox Code Playgroud)

谢谢布兰登,只是等待那个让我回答自己问题的6小时延迟的事情.

  • 这不会让其他方法比"GET"通过吗? (4认同)
  • 如果您只希望它在您的生产环境中工作,您可以将`&& process.env.NODE_ENV ==="production"放入条件中. (3认同)

Joa*_*uez 21

接受的答案中包含一个硬编码域,如果您在多个域上使用相同的代码(例如:dev-yourapp.com,test-yourapp.com,yourapp.com),则该域名不太好.

请改用:

/* 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 */
});
Run Code Online (Sandbox Code Playgroud)

https://blog.mako.ai/2016/03/30/redirect-http-to-https-on-heroku-and-node-generally/


小智 16

我写了一个小节点模块,在快递项目上强制执行SSL.它既适用于标准情况,也适用于反向代理(Heroku,nodejitsu等)

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


sim*_*imo 6

如果要测试x-forwarded-protolocalhost上的标头,可以使用nginx设置代理节点应用程序所有请求的vhost文件.您的nginx vhost配置文件可能如下所示

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

这里的重要部分是您将所有请求代理到localhost端口3000(这是您的节点应用程序正在运行的地方),并且您正在设置一堆标头,包括 X-Forwarded-Proto

然后在您的应用程序中检测该标头照常

表达

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()
  })
Run Code Online (Sandbox Code Playgroud)

兴亚

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
})
Run Code Online (Sandbox Code Playgroud)

主机

最后,您必须将此行添加到您的hosts文件中

127.0.0.1 dummy.com
Run Code Online (Sandbox Code Playgroud)


Jul*_*nec 6

你应该看看heroku-ssl-redirect。它就像一个魅力!

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);
Run Code Online (Sandbox Code Playgroud)