Node.js 在Express/Node中通过https强制请求
我有一个Express.js(v2.5.8)(节点v0.6.12)服务器在端口3100上运行。它的前端是Nginx,它将http和https请求代理到端口3100 我想通过https强制某些URL。以下是一个示例(应用程序是我的Express服务器): ensureSec是我试图用来检查连接是否通过ssl的函数:Node.js 在Express/Node中通过https强制请求,node.js,express,Node.js,Express,我有一个Express.js(v2.5.8)(节点v0.6.12)服务器在端口3100上运行。它的前端是Nginx,它将http和https请求代理到端口3100 我想通过https强制某些URL。以下是一个示例(应用程序是我的Express服务器): ensureSec是我试图用来检查连接是否通过ssl的函数: function ensureSec(req, res, next) { if (req.session.ssl == true) { return next
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);
}
}
重定向正常,但节点(在超时后)抛出一个错误,表示“无法获取/applyNow”
重定向到ssl的正确方法是什么?您需要两个不同的express
app
对象来执行此操作。express服务器的每个实例一次只能侦听一个协议。这些都可以在一个node.js进程中完成,但您需要两个不同配置的express serverapp
实例,一个用于http,另一个用于https。有关示例,请参见我的答案:
另见:
还要注意,您不应该分配req.session.ssl
。将其设置为true并不会神奇地使客户端与TLS而不是明文HTTP连接。它是只读属性。分配它没有效果
还应注意,不能在单个端口上同时运行http和https。这就是http使用80和https使用443的原因
当您收到
无法获取/applyNow
错误时,这意味着您的express routes从未与请求路径匹配,因此您的ensureSec
中间件从未被调用。您可以在nginx服务器上配置ssl端口,并像其他请求一样将代理请求配置到node.js
无需更改node.js应用程序。只需在nginx上配置443端口,并向node.js应用程序发送证书和代理请求。要补充Peter Lyons所说的,express要求您在一个端口上只运行一台服务器。如果您尝试在一个端口上运行两个http服务器,它将抛出EADDRINUSE错误 据我所知,您正在使用nginx协商SSL,并将http和https请求代理到您的Express应用程序。如果可能的话,我会选择在nginx中解决这个问题,但如果nginx不知道应该保护哪些路径(即仅通过https提供),或者出于其他原因,您希望在express app中这样做,以下是一些信息: 您应该从nginx获得
X-Forwarded-Proto
,仅当原始协议为https时才设置为https
。以下是在nginx中执行此操作的方法:
proxy_set_header X-Forwarded-Proto https;
我还将转发主机
标题:
proxy_set_header Host $http_host;
在您的express应用程序中,检查该项,或重定向到标题和请求路径中的主机(express将其解析为req.path
,因此您不必):
如下所述:,使用Nginx,您可以利用“x-forwarded-proto”标头:
当您在前端使用Nginx时,实现这一点的最干净、最简单的方法是将Nginx中的http URL转发(重写)到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-*头字段可能是可信的,否则很容易被欺骗。”
我正在使用Nginx。Nginx可以处理http和https连接,因此我可以从我的应用程序中卸载它们。我只需要强制一些路径通过ssl运行。同样,您需要两个不同的端口和两个不同的express app实例。真正地这可以是一个node.js进程,您可以强制某些http路径重定向到https,但不能在同一端口上同时运行http和https等两种完全不同的协议。这不是node.js的限制,而是协议的设计。Peter,据我所知,Rob前面有一个nginx服务器,将请求代理到node.js服务器。因此,对于express应用程序,所有请求都是http。但是有些路径,Rob不希望express服务器处理,除非它是一个https请求(到nginx)。我建议改为在nginx中强制执行,这似乎简单得多。另外,我的理解是Rob使用
req.session.ssl
跟踪客户端是否通过https连接,这似乎不可靠(在正确的情况下需要重置)。啊,我误解了这个问题。谢谢,是的,会话值不可靠。谢谢。我已经这样做了。我只是想保护某些路径。我想在node应用程序中而不是nginx中这样做。这样做使部署更容易。X-Forwarded-Proto头文件实际上是一块隐藏的宝石。修好了,谢谢。
function ensureSec(req, res, next){
if (req.headers["x-forwarded-proto"] === "https"){
return next();
}
res.redirect("https://" + req.headers.host + req.url);
});
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;