在Express / Node中通过https强制请求

我在端口3100上运行了一个Express.js(v 2.5.8)(节点v0.6.12)服务器。它由Nginx前端实现,它将http和https请求代理到端口3100。

我想通过https强制某些url。 这是一个例子(应用程序是我的快递服务器):

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

redirect工作,但节点(超时后)抛出一个错误说:不能GET / applyNow

什么是redirect到ssl的正确方法?

据我所知,你正在使用nginx协商SSL和代理的http和https请求到您的快递应用程序。 如果可能的话,我会select在nginx中解决这个问题,但是如果nginx无法知道哪些path应该受到保护(即只能通过https访问),或者您想在快速应用程序中执行此操作,信息:

您应该从nginx获得X-Forwarded-Proto ,仅在原始协议为https时才设置为https。 下面是你如何在nginx中做到这一点:

 proxy_set_header X-Forwarded-Proto https; 

我也会转发Host头:

 proxy_set_header Host $http_host; 

在您的快速应用程序,检查,或在标题和请求的pathredirect到主机(快递parsing到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对象来执行此操作 快速服务器的每个实例一次只能在一个协议上进行监听。 这可以全部在一个node.js过程中,但是您需要2个不同configuration的快速服务器app实例,一个用于http,另一个用于https。 看到我的答案为例:

如何在Express.js中强制使用SSL / https

另请参阅: 自动HTTPS连接/使用node.js / expressredirect ?

还要注意,你不应该分配req.session.ssl 。 将其设置为true并不奇妙地使得客户端连接TLS而不是明文HTTP。 这是一个只读属性。 分配它没有效果。

您还应该注意,您不能在单个端口上运行http和https。 这就是为什么http使用80和https使用443。

当你得到Cannot GET /applyNow错误,这意味着你的expresspath永远不匹配请求path,因此你的ensureSec中间件从来没有被调用过。

您可以在您的nginx服务器上configurationssl端口,并像其他请求一样将请求代理到node.js。

http://nginx.org/en/docs/http/configuring_https_servers.html

无需更改node.js应用程序。 只需在nginx上configuration443端口,并将证书和代理请求发送到node.js应用程序。

为了补充Peter Lyons所说的话,明确规定你只能在一个端口上运行一台服务器。 如果你尝试在一个端口上运行两个http服务器,它会抛出一个EADDRINUSE错误。

正如在这里解释的: http : //elias.kg/post/14971446990/force-ssl-with-express-js-on-heroku-nginx ,与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); }); 

正如你在前端使用Nginx一样,最简单和最简单的方法是将Nginx中的http URLs转发(重写)为HTTPS,而不是尝试在Express中redirect。 这可以如下完成:

 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('信任代理');

“在反向代理(如Varnish或Nginx)后面使用Express是微不足道的,但它确实需要configuration。通过通过app.enable('trust proxy')启用”trust proxy“设置,Express将知道它位于代理而X-Forwarded- *头域可能是可信的,否则可能很容易被欺骗。

表示在代理doco后面