通过https在高速/节点上强制请求
我在端口3100上运行Express.js(v 2.5.8)(节点v0.6.12)服务器。它由Nginx前端实现,它将http和https请求同时代理为端口3100.通过https在高速/节点上强制请求
我想通过https强制某些URL。下面是一个例子(应用程序是我的Express服务器):
app.get('/applyNow', ensureSec, secure.showApplication);
ensureSec的是,我试图用它来检查,如果连接是通过SSL功能:
function ensureSec(req, res, next) {
if (req.session.ssl == true) {
return next();
} else {
req.session.ssl = true;
res.redirect('https://' + url.parse(req.headers.referer).host +
url.parse(req.url).pathname);
}
}
重定向的作品,但节点(在它超时后)抛出一个错误,说'不能GET/applyNow
什么是重定向到ssl的正确方法?
据我所知,您正在使用nginx协商SSL并将http和https请求代理到您的Express应用程序。如果可能的话,我会选择在nginx中解决这个问题,但是如果nginx无法知道哪些路径应该受到保护(即只能通过https访问)或者您想在其他原因的快速应用程序中执行此操作,以下是一些信息:
您应该从nginx获得X-Forwarded-Proto
,仅当原协议为https时才设置为https
。这里是你如何做到这一点的nginx:
proxy_set_header X-Forwarded-Proto https;
我也转发Host
头:
proxy_set_header Host $http_host;
在您的明确程序,检查是否存在,或重定向到页眉和请求的主机路(快车解析,为req.path
,所以你不必):
function ensureSec(req, res, next) {
if (req.headers['x-forwarded-proto'] == 'https') {
return next();
} else {
res.redirect('https://' + req.headers.host + req.path);
}
}
您需要2个不同的快递app
对象才能做到这一点。 Express服务器的每个实例一次只能正确监听一个协议。这可以全部在一个node.js进程中,但需要2个不同配置的快速服务器app
实例,一个用于http,另一个用于https。见我的答案为例:
How to force SSL/https in Express.js
参见:Automatic HTTPS connection/redirect with node.js/express?
另请注意,您不应指定req.session.ssl
。将它设置为true并不奇妙地使得客户端与TLS而不是明文HTTP相连接。这是一个只读属性。分配它没有效果。
您还应该注意,您不能在单个端口上运行http和https。这就是为什么HTTP使用80和HTTPS使用443
当你拿到Cannot GET /applyNow
错误,这意味着您的明确路线从来不匹配的请求路径,因此您ensureSec
中间件从来没有叫。
我正在使用Nginx。 Nginx可以处理http和https连接,所以我可以从我的应用中卸载它。我只需要强制一些路径来运行ssl。 – 2012-03-15 13:26:59
同样,您需要2个不同的端口和2个不同的快速应用程序实例。真。这可以都是一个node.js进程,你可以强制一些http路径重定向到https,但是你不能在同一个端口上同时运行两个完全不同的协议,例如http和https。这不是node.js的限制,它是协议设计的方式。 – 2012-03-15 13:32:08
Peter,据我了解的问题,Rob在前面有一个nginx服务器,将请求代理到一个node.js服务器。所以,对于快速应用程序,所有请求都是http。但是有些路径,Rob不希望快速服务器处理,除非它是https请求(对nginx)。我建议用nginx来强制执行,这看起来简单得多。另外,我的理解是,Rob使用'req.session.ssl'来跟踪通过https连接的客户端,这看起来很片面(你需要在正确的情况下重置)。 – 2012-03-15 17:01:59
您可以在您的nginx服务器上配置ssl端口,并像对其他请求一样配置对node.js的代理请求。
http://nginx.org/en/docs/http/configuring_https_servers.html
无需更换的node.js应用程序。只需在nginx上配置443端口,并将证书和代理请求发送到node.js应用程序。
谢谢。我已经这样做了。我只是想保护某些路径。我想在节点应用程序中而不是在nginx中这样做。这样做使部署更容易。 – 2012-03-15 22:00:22
要添加到Peter Lyons所说的内容,明确规定您只能在一个端口上运行一台服务器。如果你尝试在一个端口上运行两个http服务器,它会抛出一个EADDRINUSE错误。
是的,谢谢。 – 2012-03-15 22:00:44
如这里解释说:http://elias.kg/post/14971446990/force-ssl-with-express-js-on-heroku-nginx,与Nginx的可以采取“X-优势转发,原”标题:
function ensureSec(req, res, next){
if (req.headers["x-forwarded-proto"] === "https"){
return next();
}
res.redirect("https://" + req.headers.host + req.url);
});
当你在前端使用Nginx的,实现这一目标的最清洁,最简单的方法就是(重写)的HTTP URL中的Nginx转发到HTTPS,而不是试图重定向在Express中。
server {
listen 12.34.56.78:80;
server_name yourserver.com;
location/{
rewrite^https://$server_name$request_uri permanent;
}
}
您可以使用此行改写:
rewrite^https://ducklington.org$request_uri permanent;
刚刚成立了自己的位置,以配合您需要转发到https航线或规则,这可以如下完成。
app.enable('trust proxy');
“在反向代理(如Varnish或Nginx)后面使用Express很简单,但它需要配置。通过通过app.enable('trust proxy')启用”trust proxy“设置,Express将知道它是坐在代理后面,并且X-Forwarded- *标头字段可能是可信的,否则可能很容易被欺骗。“
这看起来对我来说是正确的解决方案。谢谢! – 2012-03-15 22:01:10
X-Forwarded-Proto标题确实是一个隐藏的宝石。修正它,谢谢。 – 2015-04-12 07:45:14