Google app engine 在应用程序引擎灵活环境自定义运行时强制SSL
我们正在一个基于openjdk:8的Dockerfile的AppEngine灵活定制运行时上运行Metabase实例。目前,它允许访问和。我想通过将所有http流量重定向到https来强制SSL Dockerfile的外观如下所示:Google app engine 在应用程序引擎灵活环境自定义运行时强制SSL,google-app-engine,ssl,app-engine-flexible,metabase,Google App Engine,Ssl,App Engine Flexible,Metabase,我们正在一个基于openjdk:8的Dockerfile的AppEngine灵活定制运行时上运行Metabase实例。目前,它允许访问和。我想通过将所有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.
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
但在自定义运行时中,我们无法访问这样的处理程序。有没有办法配置Flexible runtime以对所有流量执行重定向?App Engine Flex根本不支持处理程序:
如果需要https://重定向,则需要从应用程序内部执行。对不起 由于您的应用程序(
app.yaml中的env:flex
)在终止SSL连接的nginx反向代理后运行,因此您需要检查X-FORWARDED-PROTO
头,该头将是http
或https
。如果是http
,那么您可以执行重定向。这就是对我有效的方法。在我的例子中,使用在云站点应用程序引擎灵活环境中运行的基于环回的NodeJS应用程序
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,但修改为使用req.protocol
而不是req.secure
,也仅在未在开发模式下运行时重定向)server/server.js
以请求:
var httpsRedirect = require('./middleware/https-redirect');
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
头
参考资料:
- 回答得晚了,但为了做到这一点,我不得不付出很多努力
我跟踪了各种链接,其中提到了以下代码
app.use(function(req, res, next) {
if(!req.secure) {
return res.redirect(['https://', req.get('Host'), req.url].join(''));
}
next();
});
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();
});
这可能适用于其他云供应商
但在GCP中,正如@zengabor正确提到的,我们的应用程序将运行在一个终止SSL连接的nginx反向代理之后,我们需要检查X-FORWARDED-PROTO
,这可以通过以下代码完成:
app.use(function(req, res, next) {
if(!req.secure) {
return res.redirect(['https://', req.get('Host'), req.url].join(''));
}
next();
});
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.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);
}
});
下面是我使用的Node.js Express代码:
//设置env变量REQUIRE\u HTTPS=1以启用此中间件
.使用(功能(req、res、next){
//将HTTP重定向到HTTPS
如果(!process.env.REQUIRE_HTTPS)返回next();
如果(请求头[“x-forwarded-proto”]=“https”)返回next();
如果(req.protocol==“https”)返回下一步();
res.redirect(301,`https://${req.hostname}${req.url}`);
})
将其作为Express应用程序中的第一个中间件
此代码假设您正在使用http/https的标准端口,就像在AppEngine上一样。您的域提供商是否提供域转发?您可以将所有
http:
转发到https:
@GAEfan这将仅适用于自定义域,并且appspot.com项目子域将允许http而不进行转发,对吗?正确,它仅适用于自定义域。我不知道appspot域有内置的。您可能需要测试https
的请求头,并强制您自己重定向非https请求。我的印象是,我没有能力修改nginx配置()。我使用的是Metabase,它明确决定这应该由托管平台支持,而不是由它们的工具支持。他们有一个EB配置,可以正确设置重定向(),但似乎没有办法在appengine flex上使用。由于Metabase似乎是开源的,所以从技术上讲可以扩展它。:)确认“X-Forwarded-Proto”标头今天存在,并且为“http”或“https”。这是否仅适用于Java应用程序?还是什么都有?我在下面的应用程序中这样做了,但我得到的“重定向你太多次了”。我认为https是在nginx本身上终止的,因此它总是给我提供http协议和false安全协议。