【问题标题】:Force SSL on App Engine Flexible Environment Custom Runtime在 App Engine 柔性环境自定义运行时强制 SSL
【发布时间】:2017-06-16 03:12:45
【问题描述】:

我们正在使用基于 openjdk:8 的 Dockerfile 在 App Engine 灵活自定义运行时上运行 Metabase 实例。目前它允许访问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

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

【问题讨论】:

  • 您的域名提供商是否提供域名转发?您可以将所有http: 转发到https:
  • @GAEfan 这仅适用于自定义域,并且项目 appspot.com 子域将允许 http 不转发,对吧?
  • 正确,它只适用于自定义域。我不知道 apppot 域的内置功能。您可能需要测试 https 的请求标头,并对非 https 请求强制重定向。

标签: google-app-engine ssl app-engine-flexible metabase


【解决方案1】:

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

我关注了提到以下代码的各种链接,

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

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

但是在@zengabor 正确提到的GCP 中,我们的应用程序将在终止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 的代码后添加我的答案,我不得不再次搜索如何实现它。所以上面是可以工作的现成代码。

【讨论】:

  • 使用状态码 307 与 GET 以外的方法一起工作很重要:res.redirect(307, `https://${req.get('Host')}${req.url}`);
【解决方案2】:

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

如果您需要 https:// 重定向,则需要在您的应用程序中进行。对不起!

【讨论】:

  • 这仅适用于 Java 应用程序吗?还是什么都有?
  • 我在此 stackoverflow.com/questions/10697660/force-ssl-with-expressjs-3 之后的应用程序中这样做了,但我收到“重定向您太​​多次。”。我认为 https 终止于 nginx 本身,因此它总是给我提供 http 协议和 false 安全协议。
【解决方案3】:

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

【讨论】:

  • 我的印象是我没有能力修改 nginx 配置 (stackoverflow.com/questions/40853799/…)。我正在使用 Metabase,它已明确决定托管平台而不是他们的工具应该支持这一点。他们有一个 EB 配置,可以正确设置重定向 (github.com/metabase/metabase/issues/1356),但似乎在 appengine flex 上没有办法。
  • 由于 Metabase 似乎是开源的,因此在技术上可以对其进行扩展。 :)
  • 确认今天存在“X-Forwarded-Proto”标头并且是“http”或“https”。
【解决方案4】:

这对我有用。在我的例子中,使用在 Cloud Sites App Engine 柔性环境中运行的基于 Loopback 的 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();
      };
    };
    

    (基于帖子http://www.jonxie.com/blog/2014/11/12/setting-up-loopback-to-use-https-and-ssl-certificates/中的第8步,但修改为使用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 标头。

参考资料:

【讨论】:

    【解决方案5】:

    使用以下代码

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

    【讨论】:

      【解决方案6】:

      这是我使用的 Node.js Express 代码:

      // 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 上的情况一样。

      【讨论】:

        猜你喜欢
        • 2018-08-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-14
        • 1970-01-01
        • 1970-01-01
        • 2018-03-29
        • 2019-04-24
        相关资源
        最近更新 更多