在应用引擎灵活环境中强制使用 SSL 自定义运行时



我们正在 App Engine 灵活的自定义运行时上运行元数据库的实例,其中包含基于 openjdk:8 的 Dockerfile。目前它允许访问 http://[metabase-project].appspot.com/和 https://[metabase-project].appspot.com/。我想通过将所有 http 流量重定向到 https 来强制 SSL。

Dockerfile 看起来像这样:

FROM openjdk:8
ADD https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 ./cloud_sql_proxy
ADD http://downloads.metabase.com/v0.21.1/metabase.jar ./metabase.jar
CMD ./cloud_sql_proxy -instances=$INSTANCE=tcp:$MB_DB_PORT -dir=/cloudsql & java -jar ./metabase.jar

我们的app.yaml看起来像:

service: metabase
runtime: custom
env: flex

在普通的App Engine app.yaml文件中,我想添加:

handlers:
- url: [something]
  secure: always

但在自定义运行时中,我们无法访问这样的处理程序。有没有办法配置灵活运行时以对所有流量执行重定向?

回答晚了,但我不得不为此付出很多努力。

我点击了各种链接,其中提到了以下代码,

app.use(function(req, res, next) {
  if(!req.secure) {
    return res.redirect(['https://', req.get('Host'), req.url].join(''));
  }
  next();
});

这可能适用于其他云供应商。

但是在 GCP 中,正如 @zengabor 正确提到的,我们的应用程序将在终止 SSL 连接的 nginx 反向代理后面运行,我们需要检查可以通过以下代码完成的X-FORWARDED-PROTO

app.use(function(req, res, next) {
  if(req.headers['x-forwarded-proto'] && req.headers['x-forwarded-proto'] === "http") {
    return res.redirect(['https://', req.get('Host'), req.url].join(''));
  }
  next();
});

只是添加我的答案,因为在阅读@zengabor的代码后,我不得不再次搜索如何实现它。所以上面是可以工作的现成代码。

App Engine Flex 根本不支持处理程序:https://cloud.google.com/appengine/docs/flexible/java/upgrading#appyaml_changes

如果需要 https://重定向,则需要从应用程序内部执行此操作。 不好意思!

由于您的应用程序(在app.yaml中env: flex)在终止SSL连接的nginx反向代理后面运行,因此您需要检查X-FORWARDED-PROTO标头,该标头将为httphttps。如果是http,那么您可以进行重定向。

这就是对我有用的。在我的情况下,使用在Cloud Sites App Engine灵活环境中运行的基于环回的NodeJS应用程序。

    创建
  1. 中间件,例如使用以下代码创建server/middleware/https-redirect.js

    /**
    * Create a middleware to redirect http requests to https
    * @param {Object} options Options
    * @returns {Function} The express middleware handler
    */
    module.exports = function(options) {
      options = options || {};
      var httpsPort = options.httpsPort || 443;
      return function(req, res, next) {
        if (req.protocol != 'https' && process.env.NODE_ENV !== 'development') {
          var parts = req.get('host').split(':');
          var host = parts[0] || '127.0.0.1';
          return res.redirect('https://' + host + ':' + httpsPort + req.url);
        }
        next();
      };
    };
    

    (基于帖子中的步骤8 http://www.jonxie.com/blog/2014/11/12/setting-up-loopback-to-use-https-and-ssl-certificates/但修改为使用req.protocol而不是req.secure,也只有在不在开发模式下运行时才会重定向)

  2. 修改文件server/server.js以请求:

    var httpsRedirect = require('./middleware/https-redirect');
    
  3. 然后,在引导行之后:

    var httpsPort = app.get('https-port');
    app.use(httpsRedirect({httpsPort: httpsPort}));
    app.set('trust proxy', true)
    

设置app.set('trust proxy', true)将允许 req.protocol 读取 X-Forwarded-Proto 标头。

引用:

  • http://expressjs.com/es/api.html#req.protocol
  • http://expressjs.com/en/guide/behind-proxies.html
  • http://www.jonxie.com/blog/2014/11/12/setting-up-loopback-to-use-https-and-ssl-certificates/

使用以下代码

app.use (function (req, res, next) {
  var schema = (req.headers['x-forwarded-proto'] || '').toLowerCase();
  if (schema === 'https') {
    next();
  } else {
    res.redirect('https://' + req.headers.host + req.url);
  }
});
这是我

使用的节点.js 快速代码:

// set the env variable REQUIRE_HTTPS=1 to enable this middleware
.use(function(req, res, next) {
    // Redirect HTTP to HTTPS
    if (!process.env.REQUIRE_HTTPS) return next();
    if (req.headers["x-forwarded-proto"] === "https") return next();
    if (req.protocol === "https") return next();
    res.redirect(301, `https://${req.hostname}${req.url}`);
})

将其作为 Express 应用程序中的第一个中间件。

此代码假定您使用 http/https 的标准端口,就像您在 AppEngine 上一样。

相关内容

  • 没有找到相关文章

最新更新